void *handle_connection(void *arg) { st_netfd_t client_nfd = (st_netfd_t)arg; struct http_stream *s = http_stream_create(HTTP_SERVER, SEC2USEC(10)); char buf[4*1024]; for (;;) { if (http_stream_request_read(s, client_nfd) < 0) break; http_request_debug_print(s->req, stderr); size_t total = 0; for (;;) { ssize_t nr = sizeof(buf); int status = http_stream_read(s, buf, &nr); fprintf(stderr, "http_stream_read nr: %zd\n", nr); if (nr < 0 || status != HTTP_STREAM_OK) { goto done; } if (nr == 0) break; /*fwrite(buf, sizeof(char), nr, stdout);*/ total += nr; } fprintf(stderr, "http_stream_read total: %zu\n", total); http_response_clear(s->resp); s->resp->http_version = "HTTP/1.1"; s->resp->status_code = 200; s->resp->reason = "OK"; http_response_header_append(s->resp, "Content-type", "text/html"); /*http_response_header_append(s->resp, "Connection", "close");*/ http_response_set_body(s->resp, "<H2>It worked!</H2>"); ssize_t nw = http_stream_response_send(s, 1); fprintf(stderr, "http_stream_response_send: %zd\n", nw); /* TODO: break loop if HTTP/1.0 and not keep-alive */ } done: fprintf(stderr, "exiting handle_connection\n"); http_stream_close(s); return NULL; }
/* Simple error response */ void http_send_error(struct http_client *c, short code, const char *msg) { struct http_response resp; http_response_init(&resp, code, msg); resp.http_version = c->http_version; http_response_set_connection_header(c, &resp); http_response_set_body(&resp, NULL, 0); http_response_write(&resp, c->fd); http_client_reset(c); }
/* Adobe flash cross-domain request */ void http_crossdomain(struct http_client *c) { struct http_response resp; char out[] = "<?xml version=\"1.0\"?>\n" "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n" "<cross-domain-policy>\n" "<allow-access-from domain=\"*\" />\n" "</cross-domain-policy>\n"; http_response_init(&resp, 200, "OK"); resp.http_version = c->http_version; http_response_set_connection_header(c, &resp); http_response_set_header(&resp, "Content-Type", "application/xml"); http_response_set_body(&resp, out, sizeof(out)-1); http_response_write(&resp, c->fd); http_client_reset(c); }
void webserver_send_response(ClientSocket* client, enum EHttpStatus status, const char* body, const char* content_type) { // Build the Content-Length string char content_length[20] = {0}; snprintf(content_length, 20, "%zu", (body ? strlen(body) : 0)); if (!content_type) { content_type = "text/plain"; } // Build the response object HttpResponse* res = http_response_new(); http_response_set_status(res, HTTP_VERSION_1_0, status); http_response_add_header(res, "Server", "webserver"); http_response_add_header(res, "Content-Length", content_length); if (body) { http_response_add_header(res, "Content-Type", content_type); } if (body) { http_response_set_body(res, body); } // Send the response and clean up client_socket_send(client, http_response_string(res), http_response_length(res)); http_response_free(res); }
void format_send_reply(struct cmd *cmd, const char *p, size_t sz, const char *content_type) { int free_cmd = 1; const char *ct = cmd->mime?cmd->mime:content_type; struct http_response *resp; if(cmd->is_websocket) { ws_reply(cmd, p, sz); /* If it's a subscribe command, there'll be more responses */ if(!cmd_is_subscribe(cmd)) cmd_free(cmd); return; } if(cmd_is_subscribe(cmd)) { free_cmd = 0; /* start streaming */ if(cmd->started_responding == 0) { cmd->started_responding = 1; resp = http_response_init(cmd->w, 200, "OK"); resp->http_version = cmd->http_version; if(cmd->filename) { http_response_set_header(resp, "Content-Disposition", cmd->filename); } http_response_set_header(resp, "Content-Type", ct); http_response_set_keep_alive(resp, 1); http_response_set_header(resp, "Transfer-Encoding", "chunked"); http_response_set_body(resp, p, sz); http_response_write(resp, cmd->fd); } else { /* Asynchronous chunk write. */ http_response_write_chunk(cmd->fd, cmd->w, p, sz); } } else { /* compute ETag */ char *etag = etag_new(p, sz); if(etag) { /* check If-None-Match */ if(cmd->if_none_match && strcmp(cmd->if_none_match, etag) == 0) { /* SAME! send 304. */ resp = http_response_init(cmd->w, 304, "Not Modified"); } else { resp = http_response_init(cmd->w, 200, "OK"); if(cmd->filename) { http_response_set_header(resp, "Content-Disposition", cmd->filename); } http_response_set_header(resp, "Content-Type", ct); http_response_set_header(resp, "ETag", etag); http_response_set_body(resp, p, sz); } resp->http_version = cmd->http_version; http_response_set_keep_alive(resp, cmd->keep_alive); http_response_write(resp, cmd->fd); free(etag); } else { format_send_error(cmd, 503, "Service Unavailable"); } } /* cleanup */ if(free_cmd) { cmd_free(cmd); } }