示例#1
0
static nxweb_result curtime_generate_cache_key(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_response* resp) {
  if (!req->get_method || req->content_length) return NXWEB_OK; // do not cache POST requests, etc.
  char* key=nxb_alloc_obj(req->nxb, strlen(req->uri)+2);
  *key=' ';
  strcpy(key+1, req->uri);
  resp->cache_key=key;
  resp->cache_key_root_len=1;
  return NXWEB_OK;
}
示例#2
0
static nxweb_result download_on_request(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_response* resp) 
{
    nxweb_parse_request_parameters( req, 0 );
    const char *name_space = nx_simple_map_get_nocase( req->parameters, "namespace" );

    char * url = malloc(strlen(req->path_info)+1);
    if (!url) {return NXWEB_ERROR;}
    strcpy(url, req->path_info);
    url[strlen(req->path_info)] = '\0';

    nxweb_url_decode( url, 0 );
    char *fname = url, *temp;
    while (temp = strstr(fname, "/")) {fname = temp + 1;}

    char *strip_args = strstr(fname, "?");

    int fname_len = strip_args ? (strip_args - fname) : strlen(fname);
    char fname_with_space[1024] = {0};
    if ( strlen(url) > sizeof(fname_with_space)-1 ) {
	char err_msg[1024] = {0};
	snprintf( err_msg, sizeof(err_msg)-1, 
		"<html><body>File not found<br/>namespace:%s<br/>filename:%.*s</body></html>", 
		name_space, fname_len, fname );
	nxweb_send_http_error(resp, 404, err_msg);
	resp->keep_alive=0;
	free(url);
	return NXWEB_MISS;
    }

    if( name_space ) {sprintf( fname_with_space, "%s:/", name_space);}
    else {strcpy( fname_with_space, ":/" );}

    strncat( fname_with_space, fname, fname_len );

    size_t file_size = 0;
    char *pfile_data = kcdbget( g_kcdb, fname_with_space, strlen(fname_with_space), &file_size );
    if ( pfile_data == NULL ) {
	char err_msg[1024] = {0};
	snprintf( err_msg, sizeof(err_msg)-1, 
		"<html><body>File not found<br/>namespace:%s<br/>filename:%.*s</body></html>", 
		name_space, fname_len, fname );
	nxweb_send_http_error(resp, 404, err_msg);
	resp->keep_alive=0;
	free(url);
	return NXWEB_MISS;
    }

    KC_DATA *ptmp = nxb_alloc_obj(req->nxb, sizeof(KC_DATA));
    nxweb_set_request_data(req, UPLOAD_HANDLER_KEY, (nxe_data)(void *)ptmp, upload_request_data_finalize);
    ptmp->data_ptr = pfile_data;

    nxweb_send_data( resp, pfile_data + RECORD_HEADER_LEN, file_size - RECORD_HEADER_LEN, "application/octet-stream" );
    free(url);
    return NXWEB_OK;
}
示例#3
0
文件: python.c 项目: liexusong/NXWEB
static nxweb_result python_on_post_data(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_response* resp) {
  if (req->content_length>0 && req->content_length<NXWEB_MAX_REQUEST_BODY_SIZE) {
    // fallback to default in-memory buffering
    return NXWEB_NEXT;
  }
  if (!conn->handler->dir) {
    nxweb_log_warning("python handler temp upload file dir not set => skipping file buffering for %s", req->uri);
    return NXWEB_NEXT;
  }
  nxe_ssize_t upload_size_limit=conn->handler->size? conn->handler->size : NXWEB_MAX_PYTHON_UPLOAD_SIZE;
  if (req->content_length > upload_size_limit) {
    nxweb_send_http_error(resp, 413, "Request Entity Too Large");
    resp->keep_alive=0; // close connection
    nxweb_start_sending_response(conn, resp);
    return NXWEB_OK;
  }
  char* fname_template=nxb_alloc_obj(req->nxb, strlen(conn->handler->dir)+sizeof("/py_upload_tmp_XXXXXX")+1);
  strcat(strcpy(fname_template, conn->handler->dir), "/py_upload_tmp_XXXXXX");
  if (nxweb_mkpath(fname_template, 0755)==-1) {
    nxweb_log_error("can't create path to temp upload file %s; check permissions", fname_template);
    nxweb_send_http_error(resp, 500, "Internal Server Error");
    resp->keep_alive=0; // close connection
    nxweb_start_sending_response(conn, resp);
    return NXWEB_OK;
  }
  int fd=mkstemp(fname_template);
  if (fd==-1) {
    nxweb_log_error("can't open (mkstemp()) temp upload file for %s", req->uri);
    nxweb_send_http_error(resp, 500, "Internal Server Error");
    resp->keep_alive=0; // close connection
    nxweb_start_sending_response(conn, resp);
    return NXWEB_OK;
  }
  unlink(fname_template); // auto-delete on close()
  nxd_fwbuffer* fwb=nxb_alloc_obj(req->nxb, sizeof(nxd_fwbuffer));
  nxweb_set_request_data(req, PYTHON_HANDLER_KEY, (nxe_data)(void*)fwb, python_request_data_finalize);
  nxd_fwbuffer_init(fwb, fd, upload_size_limit);
  conn->hsp.cls->connect_request_body_out(&conn->hsp, &fwb->data_in);
  conn->hsp.cls->start_receiving_request_body(&conn->hsp);
  return NXWEB_OK;
}
示例#4
0
static nxweb_result nxweb_http_proxy_handler_on_headers(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_response* resp) {

  nxweb_log_debug("nxweb_http_proxy_handler_on_headers");

  nxweb_http_proxy_request_data* rdata=nxb_alloc_obj(conn->hsp.nxb, sizeof(nxweb_http_proxy_request_data));
  nxe_loop* loop=conn->tdata->loop;
  memset(rdata, 0, sizeof(nxweb_http_proxy_request_data));
  rdata->conn=conn;
  conn->hsp.req_data=rdata;
  conn->hsp.req_finalize=nxweb_http_proxy_request_finalize;
  rdata->rbuf=nxp_alloc(conn->tdata->free_rbuf_pool);
  rdata->timer_backend.super.cls.timer_cls=&timer_backend_class;
  return start_proxy_request(conn, req, rdata);
}
示例#5
0
文件: python.c 项目: liexusong/NXWEB
static nxweb_result python_on_request(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_response* resp) {
  nxb_buffer* nxb=req->nxb;
  nxweb_handler* handler=conn->handler;
  const char* request_uri=req->uri;
  char* query_string=strchr(request_uri, '?');
  int ulen=query_string? (query_string-request_uri) : strlen(request_uri);
  if (query_string) query_string++;
  int pfxlen=req->path_info? (req->path_info - req->uri) : 0;
  int plen=ulen-pfxlen;
  const char* path_info=request_uri+pfxlen;
  if (handler->uri && *handler->uri) {
    pfxlen=strlen(handler->uri);
    ulen=pfxlen+plen;
    char* u=nxb_alloc_obj(nxb, ulen+1);
    memcpy(u, handler->uri, pfxlen);
    memcpy(u+pfxlen, path_info, plen);
    u[ulen]='\0';
    request_uri=u;
    path_info=request_uri+pfxlen;
  }
  const char* host_port=req->host? strchr(req->host, ':') : 0;

  int content_fd=0;

  if (req->content_length) {
    nxd_fwbuffer* fwb=nxweb_get_request_data(req, PYTHON_HANDLER_KEY).ptr;

    if (fwb) {
      if (fwb->error || fwb->size > fwb->max_size) {
        nxweb_send_http_error(resp, 413, "Request Entity Too Large"); // most likely cause
        return NXWEB_ERROR;
      }
      else if (req->content_received!=fwb->size) {
        nxweb_log_error("content_received does not match upload stored size for %s", req->uri);
        nxweb_send_http_error(resp, 500, "Internal Server Error");
        return NXWEB_ERROR;
      }
      else {
        content_fd=fwb->fd;
        if (lseek(content_fd, 0, SEEK_SET)==-1) {
          nxweb_log_error("can't lseek() temp upload file for %s", req->uri);
          nxweb_send_http_error(resp, 500, "Internal Server Error");
          return NXWEB_ERROR;
        }
      }
    }
  }


  nxweb_log_debug("invoke python");

  PyGILState_STATE gstate=PyGILState_Ensure();

  PyObject* py_func_args=PyTuple_New(1);
  PyObject* py_environ=PyDict_New();
  assert(PyDict_Check(py_environ));

  dict_set(py_environ, "SERVER_NAME", PyString_FromStringAndSize(req->host, host_port? (host_port-req->host) : strlen(req->host)));
  dict_set(py_environ, "SERVER_PORT", PyString_FromString(host_port? host_port+1 : ""));
  dict_set(py_environ, "SERVER_PROTOCOL", PyString_FromString(req->http11? "HTTP/1.1" : "HTTP/1.0"));
  dict_set(py_environ, "SERVER_SOFTWARE", PyString_FromString(PACKAGE_STRING));
  dict_set(py_environ, "GATEWAY_INTERFACE", PyString_FromString("CGI/1.1"));
  dict_set(py_environ, "REQUEST_METHOD", PyString_FromString(req->method));
  dict_set(py_environ, "REQUEST_URI", PyString_FromStringAndSize(request_uri, ulen));
  dict_set(py_environ, "SCRIPT_NAME", PyString_FromStringAndSize(request_uri, pfxlen));
  dict_set(py_environ, "PATH_INFO", PyString_FromStringAndSize(path_info, plen));
  dict_set(py_environ, "QUERY_STRING", PyString_FromString(query_string? query_string : ""));
  dict_set(py_environ, "REMOTE_ADDR", PyString_FromString(conn->remote_addr));
  dict_set(py_environ, "CONTENT_TYPE", PyString_FromString(req->content_type? req->content_type : ""));
  dict_set(py_environ, "CONTENT_LENGTH", PyInt_FromLong(req->content_received));
  if (req->cookie) dict_set(py_environ, "HTTP_COOKIE", PyString_FromString(req->cookie));
  if (req->host) dict_set(py_environ, "HTTP_HOST", PyString_FromString(req->host));
  if (req->user_agent) dict_set(py_environ, "HTTP_USER_AGENT", PyString_FromString(req->user_agent));
  if (req->if_modified_since) {
    struct tm tm;
    gmtime_r(&req->if_modified_since, &tm);
    char ims[32];
    nxweb_format_http_time(ims, &tm);
    dict_set(py_environ, "HTTP_IF_MODIFIED_SINCE", PyString_FromString(ims));
  }

  if (req->headers) {
    // write added headers
    // encode http headers into CGI variables; see 4.1.18 in https://tools.ietf.org/html/rfc3875
    char hname[256];
    memcpy(hname, "HTTP_", 5);
    char* h=hname+5;
    nx_simple_map_entry* itr;
    for (itr=nx_simple_map_itr_begin(req->headers); itr; itr=nx_simple_map_itr_next(itr)) {
      nx_strtoupper(h, itr->name);
      char* p;
      for (p=h; *p; p++) {
        if (*p=='-') *p='_';
      }
      dict_set(py_environ, hname, PyString_FromString(itr->value));
    }
  }

  dict_set(py_environ, "wsgi.url_scheme", PyString_FromString(conn->secure? "https" : "http"));

  if (req->content_length) {
    if (content_fd) {
      dict_set(py_environ, "nxweb.req.content_fd", PyInt_FromLong(content_fd));
    }
    else {
      dict_set(py_environ, "nxweb.req.content", PyByteArray_FromStringAndSize(req->content? req->content : "", req->content_received));
    }
  }
  if (req->if_modified_since) dict_set(py_environ, "nxweb.req.if_modified_since", PyLong_FromLong(req->if_modified_since));
  dict_set(py_environ, "nxweb.req.uid", PyLong_FromLongLong(req->uid));
  if (req->parent_req) {
    nxweb_http_request* preq=req->parent_req;
    while (preq->parent_req) preq=preq->parent_req; // find root request
    if (preq->uid) {
      dict_set(py_environ, "nxweb.req.root_uid", PyLong_FromLongLong(preq->uid));
    }
  }

  // call python
  PyTuple_SetItem(py_func_args, 0, py_environ);
  PyObject* py_result=PyObject_CallObject(py_nxweb_on_request_func, py_func_args);
  Py_DECREF(py_func_args);
  if (py_result && PyTuple_Check(py_result) && PyTuple_Size(py_result)==3) {
    PyObject* py_status=PyTuple_GET_ITEM(py_result, 0);
    PyObject* py_headers=PyTuple_GET_ITEM(py_result, 1);
    PyObject* py_body=PyTuple_GET_ITEM(py_result, 2);

    if (py_status && PyString_Check(py_status)) {
      const char* status_string=PyString_AS_STRING(py_status);
      int status_code=0;
      const char* p=status_string;
      while (*p && *p>='0' && *p<='9') {
        status_code=status_code*10+(*p-'0');
        p++;
      }
      while (*p && *p==' ') p++;
      if (status_code>=200 && status_code<600 && *p) {
        resp->status_code=status_code;
        resp->status=nxb_copy_str(nxb, p);
      }
    }

    if (py_headers && PyList_Check(py_headers)) {
      const int size=PyList_Size(py_headers);
      int i;
      for (i=0; i<size; i++) {
        PyObject* py_header_tuple=PyList_GET_ITEM(py_headers, i);
        if (py_header_tuple && PyTuple_Check(py_header_tuple) && PyTuple_Size(py_header_tuple)==2) {
          PyObject* py_name=PyTuple_GET_ITEM(py_header_tuple, 0);
          PyObject* py_value=PyTuple_GET_ITEM(py_header_tuple, 1);
          if (py_name && PyString_Check(py_name) && py_value && PyString_Check(py_value)) {
            nxweb_add_response_header_safe(resp, PyString_AS_STRING(py_name), PyString_AS_STRING(py_value));
          }
        }
      }
    }

    if ((!resp->status_code || resp->status_code==200) && !resp->content_type) resp->content_type="text/html";

    char* rcontent=0;
    nxe_ssize_t rsize=0;
    if (PyByteArray_Check(py_body)) {
      rcontent=PyByteArray_AS_STRING(py_body);
      rsize=PyByteArray_Size(py_body);
    }
    else if (PyString_Check(py_body)) {
      rcontent=PyString_AS_STRING(py_body);
      rsize=PyString_Size(py_body);
    }
    if (rcontent && rsize>0) nxweb_response_append_data(resp, rcontent, rsize);
  }
  else if (py_result && PyString_Check(py_result)) {
    resp->status_code=500;
    resp->status="Internal Server Error";
    resp->content_type="text/html";
    nxweb_log_error("python call failed: %s", PyString_AS_STRING(py_result));
    nxweb_response_printf(resp, "python call failed: %H", PyString_AS_STRING(py_result));
  }
  else {
    PyErr_Print();
    nxweb_log_error("python call failed");
    nxweb_response_printf(resp, "python call failed");
  }
  Py_XDECREF(py_result);

  // Release the thread. No Python API allowed beyond this point.
  PyGILState_Release(gstate);

  nxweb_log_debug("invoke python complete");

  return NXWEB_OK;
}
示例#6
0
static nxweb_result start_proxy_request(nxweb_http_server_connection* conn, nxweb_http_request* req, nxweb_http_proxy_request_data* rdata) {

  nxweb_log_debug("start_proxy_request");

  nxe_loop* loop=conn->tdata->loop;
  nxweb_handler* handler=conn->handler;
  assert(handler->idx>=0 && handler->idx<NXWEB_MAX_PROXY_POOLS);
  nxd_http_proxy* hpx=nxd_http_proxy_pool_connect(&conn->tdata->proxy_pool[handler->idx]);
  rdata->proxy_request_complete=0;
  rdata->proxy_request_error=0;
  rdata->response_sending_started=0;
  if (hpx) {
    rdata->hpx=hpx;
    nxweb_http_request* preq=nxd_http_proxy_prepare(hpx);
    if (handler->proxy_copy_host) preq->host=req->host;
    preq->method=req->method;
    preq->head_method=req->head_method;
    preq->content_length=req->content_length;
    preq->content_type=req->content_type;
    /// Do not forward Accept-Encoding header if you want to process results (eg SSI)
    // preq->accept_encoding=req->accept_encoding;
    preq->expect_100_continue=!!req->content_length;
    if (handler->uri) {
      const char* path_info=req->path_info? req->path_info : req->uri;
      if (*handler->uri) {
        char* uri=nxb_alloc_obj(conn->hsp.nxb, strlen(handler->uri)+strlen(path_info)+1);
        strcat(strcpy(uri, handler->uri), path_info);
        preq->uri=uri;
      }
      else {
        preq->uri=path_info;
      }
    }
    else {
      preq->uri=req->uri;
    }
    preq->http11=1;
    preq->keep_alive=1;
    preq->user_agent=req->user_agent;
    preq->cookie=req->cookie;
    preq->if_modified_since=req->if_modified_since + nxd_http_proxy_pool_get_backend_time_delta(hpx->pool);
    preq->x_forwarded_for=conn->remote_addr;
    preq->x_forwarded_host=req->host;
    preq->x_forwarded_ssl=nxweb_server_config.listen_config[conn->lconf_idx].secure;
    preq->uid=req->uid;
    preq->parent_req=req->parent_req;
    preq->headers=req->headers; // need to filter these???
    nxd_http_proxy_start_request(hpx, preq);
    nxe_init_subscriber(&rdata->proxy_events_sub, &nxweb_http_server_proxy_events_sub_class);
    nxe_subscribe(loop, &hpx->hcp.events_pub, &rdata->proxy_events_sub);
    nxd_rbuffer_init(&rdata->rb_resp, rdata->rbuf, NXWEB_RBUF_SIZE);
    nxe_connect_streams(loop, &hpx->hcp.resp_body_out, &rdata->rb_resp.data_in);

    if (req->content_length) { // receive body
      nxd_rbuffer_init(&rdata->rb_req, rdata->rbuf, NXWEB_RBUF_SIZE); // use same buffer area for request and response bodies, as they do not overlap in time
      conn->hsp.cls->connect_request_body_out(&conn->hsp, &rdata->rb_req.data_in);
      nxe_connect_streams(loop, &rdata->rb_req.data_out, &hpx->hcp.req_body_in);
      req->cdstate.monitor_only=1;

      conn->hsp.cls->start_receiving_request_body(&conn->hsp);
    }
    nxe_set_timer(loop, NXWEB_TIMER_BACKEND, &rdata->timer_backend);
    return NXWEB_OK;
  }
  else {
    nxweb_http_response* resp=&conn->hsp._resp;
    nxweb_send_http_error(resp, 502, "Bad Gateway");
    return NXWEB_ERROR;
  }
}