/****************************************************************************** * subroutine: serve_post * * purpose: return response for POST request * * parameters: client_fd - client descriptor * * context - a pointer refers to HTTP context * * is_closed - an indicator if the current transaction is closed * * return: none * ******************************************************************************/ void serve_post(int client_fd, HTTPContext *context, int *is_closed) { struct tm tm; struct stat sbuf; time_t now; char buf[BUF_SIZE], dbuf[MIN_LINE]; // check file existence if (stat(context->filename, &sbuf) == 0) { serve_get(client_fd, context, is_closed); return; } // get time string now = time(0); tm = *gmtime(&now); strftime(dbuf, MIN_LINE, "%a, %d %b %Y %H:%M:%S %Z", &tm); // send response headers to client sprintf(buf, "HTTP/1.1 204 No Content\r\n"); sprintf(buf, "%sDate: %s\r\n", buf, dbuf); sprintf(buf, "%sServer: Liso/1.0\r\n", buf); if (is_closed) sprintf(buf, "%sConnection: close\r\n", buf); sprintf(buf, "%sContent-Length: 0\r\n", buf); sprintf(buf, "%sContent-Type: text/html\r\n", buf); send(client_fd, buf, strlen(buf), 0); }
/****************************************************************************** * subroutine: process_request * * purpose: handle a single request and return responses * * parameters: id - the index of the client in the pool * * p - a pointer of pool struct * * is_closed - idicator if the transaction is closed * * return: none * ******************************************************************************/ void process_request(int id, pool *p, int *is_closed) { HTTPContext *context = (HTTPContext *)calloc(1, sizeof(HTTPContext)); Log("Start processing request. \n"); // parse request line (get method, uri, version) if (parse_requestline(id, p, context, is_closed) < 0) goto Done; // check HTTP method (support GET, POST, HEAD now) if (strcasecmp(context->method, "GET") && strcasecmp(context->method, "HEAD") && strcasecmp(context->method, "POST")) { *is_closed = 1; serve_error(p->clientfd[id], "501", "Not Implemented", "The method is not valid or not implemented by the server", *is_closed); goto Done; } // check HTTP version if (strcasecmp(context->version, "HTTP/1.1")) { *is_closed = 1; serve_error(p->clientfd[id], "505", "HTTP Version not supported", "HTTP/1.0 is not supported by Liso server", *is_closed); goto Done; } // parse uri (get filename and parameters if any) parse_uri(context); // parse request headers if (parse_requestheaders(id, p, context, is_closed) < 0) goto Done; // for POST, parse request body if (!strcasecmp(context->method, "POST")) if (parse_requestbody(id, p, context, is_closed) < 0) goto Done; // send response if (!strcasecmp(context->method, "GET")) serve_get(p->clientfd[id], context, is_closed); else if (!strcasecmp(context->method, "POST")) serve_post(p->clientfd[id], context, is_closed); else if (!strcasecmp(context->method, "HEAD")) serve_head(p->clientfd[id], context, is_closed); Done: free(context); Log("End of processing request. \n"); }
ec_cbrc_t serve(ec_server_t *srv, void *u0, struct timeval *tv, bool resched) { ec_mt_t mta[16]; size_t mta_sz = sizeof mta / sizeof(ec_mt_t); ec_rep_t *rep; ec_res_t *res; char uri[U_URI_STRMAX]; bool is_proxy; u_unused_args(u0); /* Get the requested URI and method. */ dbg_if (ec_request_get_uri(srv, uri, &is_proxy) == NULL); ec_method_t method = ec_server_get_method(srv); CHAT("%s %s", ec_method_str(method), uri); /* Tell'em to use test/proxy to support Proxy-Uri's. */ if (is_proxy) { dbg_if (ec_response_set_code(srv, EC_PROXYING_NOT_SUPPORTED)); return EC_CBRC_READY; } /* See if configured for separate responses. */ if (resched == false && g_ctx.sep.tv_sec) { *tv = g_ctx.sep; u_con("reschedule %s() for %s in %llu seconds", __func__, uri, (long long) g_ctx.sep.tv_sec); return EC_CBRC_WAIT; } /* See if it is a query for the /.well-known/core URI. */ if (!strcasecmp(ec_request_get_uri_path(srv), "/.well-known/core")) { (void) serve_wkc(srv, method); return EC_CBRC_READY; } /* Get Accept'able media types. */ dbg_err_if(ec_request_get_acceptable_media_types(srv, mta, &mta_sz)); /* Try to retrieve a representation that fits client request. */ rep = ec_filesys_get_suitable_rep(g_ctx.fs, ec_server_get_url(srv), mta, mta_sz, NULL); /* If found, craft the response. */ if (rep) { dbg_err_if((res = ec_rep_get_res(rep)) == NULL); /* Make sure resource supports the requested method. * Bypass check for Proxy-Uri requests because of Publish admin * operations (will be checked in PUT/DELETE handlers.) */ if (!ec_request_via_proxy(srv) && ec_resource_check_method(res, method)) { (void) ec_response_set_code(srv, EC_METHOD_NOT_ALLOWED); return EC_CBRC_READY; } switch (method) { case EC_COAP_GET: (void) serve_get(srv, rep); return EC_CBRC_READY; case EC_COAP_DELETE: (void) serve_delete(srv, uri); return EC_CBRC_READY; case EC_COAP_PUT: (void) serve_put(srv, rep); return EC_CBRC_READY; case EC_COAP_POST: (void) serve_post(srv); return EC_CBRC_READY; default: ec_response_set_code(srv, EC_NOT_IMPLEMENTED); return EC_CBRC_READY; } } else (void) ec_response_set_code(srv, EC_NOT_FOUND); return EC_CBRC_READY; err: return EC_CBRC_ERROR; }