Add primitive url handling system to skiaserve

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1644633002

Review URL: https://codereview.chromium.org/1644633002
This commit is contained in:
joshualitt 2016-01-27 07:40:29 -08:00 committed by Commit bot
parent 8f5175842d
commit ccfdaa5f2a

View File

@ -129,6 +129,121 @@ static int process_upload_data(void* cls, enum MHD_ValueKind kind,
return MHD_YES;
}
static int SendImage(MHD_Connection* connection, const SkData* data) {
MHD_Response* response = MHD_create_response_from_buffer(data->size(),
const_cast<void*>(data->data()),
MHD_RESPMEM_MUST_COPY);
MHD_add_response_header(response, "Content-Type", "image/png");
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
return ret;
}
static int SendTemplate(MHD_Connection* connection) {
SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org"));
MHD_Response* response = MHD_create_response_from_buffer(
debuggerTemplate.size(),
(void*) const_cast<char*>(debuggerTemplate.c_str()),
MHD_RESPMEM_MUST_COPY);
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
return ret;
}
typedef int (*UrlHandler)(Request* request, MHD_Connection* connection,
const char* upload_data, size_t* upload_data_size);
int rootHandler(Request* request, MHD_Connection* connection,
const char* upload_data, size_t* upload_data_size) {
return SendTemplate(connection);
}
int postHandler(Request* request, MHD_Connection* connection,
const char* upload_data, size_t* upload_data_size) {
UploadContext* uc = request->fUploadContext;
// New connection
if (!uc) {
// TODO make this a method on request
uc = new UploadContext;
uc->connection = connection;
uc->pp = MHD_create_post_processor(connection, kBufferSize, &process_upload_data, uc);
SkASSERT(uc->pp);
request->fUploadContext = uc;
return MHD_YES;
}
// in process upload
if (0 != *upload_data_size) {
SkASSERT(uc->pp);
MHD_post_process(uc->pp, upload_data, *upload_data_size);
*upload_data_size = 0;
return MHD_YES;
}
// end of upload
MHD_destroy_post_processor(uc->pp);
uc->pp = nullptr;
// TODO response
SkString error;
SkData* data = setupAndDrawToCanvas(uc->stream.detachAsStream(), &error);
if (!data) {
// TODO send error
return MHD_YES;
}
request->fPNG.reset(data);
return SendTemplate(connection);
}
int imgHandler(Request* request, MHD_Connection* connection,
const char* upload_data, size_t* upload_data_size) {
if (request->fPNG.get()) {
SkData* data = request->fPNG.get();
return SendImage(connection, data);
}
return MHD_NO;
}
class UrlManager {
public:
UrlManager() {
// Register handlers
fHandlers.push_back({MHD_HTTP_METHOD_GET, "/", rootHandler});
fHandlers.push_back({MHD_HTTP_METHOD_POST, "/new", postHandler});
fHandlers.push_back({MHD_HTTP_METHOD_GET, "/img", imgHandler});
}
// This is clearly not efficient for a large number of urls and handlers
int invoke(Request* request, MHD_Connection* connection, const char* url, const char* method,
const char* upload_data, size_t* upload_data_size) const {
for (int i = 0; i < fHandlers.count(); i++) {
const Url& urlHandler = fHandlers[i];
if (0 == strcmp(method, urlHandler.fMethod) &&
0 == strcmp(url, urlHandler.fPath)) {
return (*urlHandler.fHandler)(request, connection, upload_data,
upload_data_size);
}
}
return MHD_NO;
}
private:
struct Url {
const char* fMethod;
const char* fPath;
UrlHandler fHandler;
};
SkTArray<Url> fHandlers;
};
const UrlManager kUrlManager;
int answer_to_connection(void* cls, struct MHD_Connection* connection,
const char* url, const char* method, const char* version,
const char* upload_data, size_t* upload_data_size,
@ -136,86 +251,7 @@ int answer_to_connection(void* cls, struct MHD_Connection* connection,
SkDebugf("New %s request for %s using version %s\n", method, url, version);
Request* request = reinterpret_cast<Request*>(cls);
MHD_Response* response;
int ret = MHD_NO;
// TODO url handlers
// handle uploads
if (0 == strcmp(method, MHD_HTTP_METHOD_POST) &&
0 == strcmp(url, "/new")) {
UploadContext* uc = request->fUploadContext;
// New connection
if (!uc) {
// TODO make this a method on request
uc = new UploadContext;
uc->connection = connection;
uc->pp = MHD_create_post_processor(connection, kBufferSize, &process_upload_data, uc);
SkASSERT(uc->pp);
request->fUploadContext = uc;
return MHD_YES;
}
// in process upload
if (0 != *upload_data_size) {
SkASSERT(uc->pp);
MHD_post_process(uc->pp, upload_data, *upload_data_size);
*upload_data_size = 0;
return MHD_YES;
}
// end of upload
MHD_destroy_post_processor(uc->pp);
uc->pp = nullptr;
// TODO response
SkString error;
SkData* data = setupAndDrawToCanvas(uc->stream.detachAsStream(), &error);
if (!data) {
// TODO send error
return MHD_YES;
}
request->fPNG.reset(data);
// TODO Hack
SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org"));
response = MHD_create_response_from_buffer(debuggerTemplate.size(),
(void*) const_cast<char*>(debuggerTemplate.c_str()),
MHD_RESPMEM_MUST_COPY);
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
} else if (0 == strcmp(method, MHD_HTTP_METHOD_GET)) {
if (0 == strcmp(url, "/")) {
SkString debuggerTemplate = generateTemplate(SkString("http://debugger.skia.org"));
response = MHD_create_response_from_buffer(debuggerTemplate.size(),
(void*) const_cast<char*>(debuggerTemplate.c_str()),
MHD_RESPMEM_MUST_COPY);
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
} else if (0 == strcmp(url, "/img")) {
if (request->fPNG.get()) {
SkData* data = request->fPNG.get();
response = MHD_create_response_from_buffer(data->size(),
const_cast<void*>(data->data()),
MHD_RESPMEM_MUST_COPY);
MHD_add_response_header(response, "Content-Type", "image/png");
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
}
}
} else {
SkFAIL("whoops, need proper error handling");
return MHD_NO;
}
return ret;
return kUrlManager.invoke(request, connection, url, method, upload_data, upload_data_size);
}
int skiaserve_main() {