@@ -2512,8 +2512,19 @@ const HookMask Do_upstream_rsp_body::HOOKS{MaskFor({Hook::URSP})};
25122512Errata
25132513Do_upstream_rsp_body::invoke (Context &ctx)
25142514{
2515+ // State allocated in transaction memory.
2516+ struct State {
2517+ TextView _view; // /< Source view for body.
2518+ TSIOBuffer _tsio_buff = nullptr ; // /< Buffer used to write body.
2519+ };
2520+
25152521 auto static transform = [](TSCont contp, TSEvent ev_code, void *) -> int {
2516- if (TSVConnClosedGet (contp)) {
2522+
2523+ if (TSVConnClosedGet (contp)) { // all done, time to clean up.
2524+ auto state = static_cast <State*>(TSContDataGet (contp));
2525+ if (state && state->_tsio_buff ) {
2526+ TSIOBufferDestroy (state->_tsio_buff );
2527+ }
25172528 TSContDestroy (contp);
25182529 return 0 ;
25192530 }
@@ -2539,14 +2550,12 @@ Do_upstream_rsp_body::invoke(Context &ctx)
25392550 TSContCall (TSVIOContGet (in_vio),
25402551 (TSVIONTodoGet (in_vio) <= 0 ) ? TS_EVENT_VCONN_WRITE_COMPLETE : TS_EVENT_VCONN_WRITE_READY, in_vio);
25412552 }
2542- // If the full is there, create the output buffer and write it, then clear it.
2543- auto view = static_cast <TextView *>(TSContDataGet (contp));
2544- if (view) {
2553+ // If the buffer isn't already there, create it and write out the view.
2554+ if ( auto state = static_cast <State *>(TSContDataGet (contp)) ; state && ! state->_tsio_buff ) {
25452555 auto out_vconn = TSTransformOutputVConnGet (contp);
2546- auto out_buff = TSIOBufferCreate ();
2547- auto out_vio = TSVConnWrite (out_vconn, contp, TSIOBufferReaderAlloc (out_buff), view->size ());
2548- TSIOBufferWrite (out_buff, view->data (), view->size ());
2549- TSContDataSet (contp, nullptr );
2556+ state->_tsio_buff = TSIOBufferCreate ();
2557+ TSIOBufferWrite (state->_tsio_buff , state->_view .data (), state->_view .size ());
2558+ auto out_vio = TSVConnWrite (out_vconn, contp, TSIOBufferReaderAlloc (state->_tsio_buff ), state->_view .size ());
25502559 TSVIOReenable (out_vio);
25512560 }
25522561 }
@@ -2575,12 +2584,12 @@ Do_upstream_rsp_body::invoke(Context &ctx)
25752584 }
25762585
25772586 if (content) {
2578- // The view contents are in the transaction data, but the full in the feature is not.
2579- // Make a copy there and pass its address to the continuation .
2580- auto ctx_view = ctx.alloc_span <TextView>( 1 );
2587+ // The view contents are in the transaction data, but the view in the feature is not.
2588+ // Put a copy in the transform @a state .
2589+ auto state = ctx.make <State>( );
25812590 auto cont = TSTransformCreate (transform, ctx._txn );
2582- ctx_view[ 0 ] = *content;
2583- TSContDataSet (cont, ctx_view. data () );
2591+ state-> _view = *content;
2592+ TSContDataSet (cont, state );
25842593 TSHttpTxnHookAdd (ctx._txn , TS_HTTP_RESPONSE_TRANSFORM_HOOK, cont);
25852594 ctx._txn .ursp_hdr ().field_obtain (" Content-Type" _tv).assign (content_type);
25862595 }
0 commit comments