msIOContext* msIO_pushStdoutToBufferAndGetOldContext() { msIOContextGroup *group = msIO_GetContextGroup(); msIOContext *old_context; /* Backup current context */ old_context = (msIOContext*) msSmallMalloc(sizeof(msIOContext)); memcpy(old_context, &group->stdout_context, sizeof(msIOContext)); msIO_installStdoutToBuffer(); return old_context; }
/** * @details This is called by `MapservAsync` and runs in a different thread to * that function. It performs the actual work of interacting with * mapserver. The code is based on the logic found in the `mapserv` program but * the output is instead buffered using the mapserver output buffering * functionality: it can then be captured and passed back to the client. * * @param req The asynchronous libuv request. */ void Map::MapservWork(uv_work_t *req) { /* No HandleScope! This is run in a separate thread: *No* contact should be made with the Node/V8 world here. */ MapBaton *baton = static_cast<MapBaton*>(req->data); mapservObj* mapserv = NULL; bool reportError = false; // flag an error as worthy of reporting if (msDebugInitFromEnv() != MS_SUCCESS) { reportError = true; goto handle_error; } mapserv = msAllocMapServObj(); msIO_installStdinFromBuffer(); // required to catch POSTS without data msIO_installStdoutToBuffer(); // required to capture mapserver output // load the CGI parameters from the environment object mapserv->request->NumParams = wrap_loadParams(mapserv->request, GetEnv, const_cast<char *>(baton->body.c_str()), baton->body.length(), static_cast<void *>(&(baton->env))); if( mapserv->request->NumParams == -1 ) { // no errors are generated by default but messages are output instead msSetError( MS_MISCERR, "No request parameters loaded", "Map::MapservWork" ); reportError = true; goto get_output; } // Copy the map into the mapservObj for this request if(!LoadMap(mapserv, baton->map)) { reportError = true; goto get_output; } // Execute the request if(msCGIDispatchRequest(mapserv) != MS_SUCCESS) { reportError = true; goto get_output; } get_output: // Get the content type. If headers other than content-type need to be // retrieved it may be best to use something along the lines of // <https://github.com/joyent/http-parser>. baton->content_type = msIO_stripStdoutBufferContentType(); msIO_stripStdoutBufferContentHeaders(); // Get the buffered output baton->buffer = msIO_getStdoutBufferBytes(); handle_error: // handle any unhandled errors errorObj *error = msGetErrorObj(); if (error && error->code != MS_NOERR) { // report the error if requested if (reportError) { baton->error = new MapserverError(error); } msResetErrorList(); // clear all handled errors } // clean up msFreeMapServObj(mapserv); msIO_resetHandlers(); msDebugCleanup(); return; }