/** * Serves a PNG file of the hash. */ void route_image(evhtp_request_t *req, void *arg) { // redisReply *reply; evhtp_uri_t *uri = req->uri; int side = 128; char *hash = ""; char *res = uri->path->full; int ind = 0; res = strtok((char *) res, "/"); while (res != NULL) { if (ind == 0) { if (strlen(res) == 32) { hash = res; } else if (strcmp(res, "avatar") == 0) { ind--; } else { route_400(req); return; } } if (ind == 1) { side = atoi(res); if (side == 0) { side = defsize; } else if (side < minsize) { side = minsize; } else if (side > maxsize) { side = maxsize; } } res = strtok(NULL, "/"); ind++; } char *etag = malloc(sizeof(char) * 1024); sprintf(etag, "\"%s-%d\"", hash, side); evhtp_kv_t *etagin = evhtp_headers_find_header(req->headers_in, "If-None-Match"); if(etagin && strcmp(etag, etagin->val) == 0) { free(etag); evhtp_send_reply(req, 304); return; } make_image(hash, req->buffer_out, side); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Content-Type", "image/png", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("Cache-Control", "public", 0, 0)); evhtp_headers_add_header(req->headers_out, evhtp_header_new("ETag", etag, 0, 1)); free(etag); evhtp_send_reply(req, 200); }
void zxy_send_content( zxy_request_context *context, const std::string& content ) { evhtp_header_t *header = evhtp_headers_find_header( context->request->headers_out, "Content-Type" ); if ( header == NULL ) { zxy_add_http_header(context, "Content-Type", "text/html"); } evbuffer_add(context->request->buffer_out, content.c_str(), content.size()); }
void zxy_printf_content( zxy_request_context *context, const char* fmt, ... ) { evhtp_header_t *header = evhtp_headers_find_header( context->request->headers_out, "Content-Type" ); if ( header == NULL ) { zxy_add_http_header(context, "Content-Type", "text/html"); } va_list args; va_start(args, fmt); evbuffer_add_vprintf(context->request->buffer_out, fmt, args); va_end(args); }
void evhtp_send_reply_chunk_start(evhtp_request_t * request, evhtp_res code) { evhtp_header_t * content_len; if (evhtp_response_needs_body(code, request->method)) { content_len = evhtp_headers_find_header(request->headers_out, "Content-Length"); switch (request->proto) { case EVHTP_PROTO_11: /* * prefer HTTP/1.1 chunked encoding to closing the connection; * note RFC 2616 section 4.4 forbids it with Content-Length: * and it's not necessary then anyway. */ evhtp_kv_rm_and_free(request->headers_out, content_len); request->chunked = 1; break; case EVHTP_PROTO_10: /* * HTTP/1.0 can be chunked as long as the Content-Length header * is set to 0 */ evhtp_kv_rm_and_free(request->headers_out, content_len); evhtp_headers_add_header(request->headers_out, evhtp_header_new("Content-Length", "0", 0, 0)); request->chunked = 1; break; default: request->chunked = 0; break; } /* switch */ } else { request->chunked = 0; } if (request->chunked == 1) { evhtp_headers_add_header(request->headers_out, evhtp_header_new("Transfer-Encoding", "chunked", 0, 0)); /* * if data already exists on the output buffer, we automagically convert * it to the first chunk. */ if (evbuffer_get_length(request->buffer_out) > 0) { char lstr[128]; int sres; sres = snprintf(lstr, sizeof(lstr), "%x\r\n", (unsigned)evbuffer_get_length(request->buffer_out)); if (sres >= sizeof(lstr) || sres < 0) { /* overflow condition, shouldn't ever get here, but lets * terminate the connection asap */ goto end; } evbuffer_prepend(request->buffer_out, lstr, strlen(lstr)); evbuffer_add(request->buffer_out, "\r\n", 2); } } end: evhtp_send_reply_start(request, code); } /* evhtp_send_reply_chunk_start */