Exemple #1
0
ngx_http_request_t *subscriber_subrequest(subscriber_t *sub, ngx_str_t *url, ngx_buf_t *body, subrequest_callback_pt cb, void *cb_data) {
  ngx_http_request_t            *r = sub->request;
  ngx_http_post_subrequest_t    *psr = ngx_pcalloc(r->pool, sizeof(*psr));
  nchan_subrequest_data_cb_t    *psrd = ngx_pcalloc(r->pool, sizeof(*psrd));
  ngx_http_request_t            *sr;

  sub->fn->reserve(sub);
  
  psr->handler = subscriber_subrequest_handler;
  psr->data = psrd;
  psrd->sub = sub;
  psrd->cb_data = cb_data;
  psrd->cb = cb;
  
  ngx_http_subrequest(r, url, NULL, &sr, psr, NGX_HTTP_SUBREQUEST_IN_MEMORY);
  
  if((sr->request_body = ngx_pcalloc(r->pool, sizeof(*sr->request_body))) == NULL) { //dummy request body 
    return NULL;
  }
  
  if(body && ngx_buf_size(body) > 0) {
    static ngx_str_t                   POST_REQUEST_STRING = {4, (u_char *)"POST "};
    size_t                             sz;
    ngx_http_request_body_t           *sr_body = sr->request_body;
    ngx_chain_t                       *fakebody_chain;
    ngx_buf_t                         *fakebody_buf;
    
    fakebody_chain = ngx_palloc(r->pool, sizeof(*fakebody_chain));
    fakebody_buf = ngx_palloc(r->pool, sizeof(*fakebody_buf));
    sr_body->bufs = fakebody_chain;
    fakebody_chain->next = NULL;
    fakebody_chain->buf = fakebody_buf;
    ngx_memzero(fakebody_buf, sizeof(*fakebody_buf));
    fakebody_buf->last_buf = 1;
    fakebody_buf->last_in_chain = 1;
    fakebody_buf->flush = 1;
    fakebody_buf->memory = 1;
    
    //just copy the buffer contents. it's inefficient but I don't care at the moment.
    //this can and should be optimized later
    sz = ngx_buf_size(body);
    fakebody_buf->start = ngx_palloc(r->pool, sz); //huuh?
    ngx_memcpy(fakebody_buf->start, body->start, sz);
    fakebody_buf->end = fakebody_buf->start + sz;
    fakebody_buf->pos = fakebody_buf->start;
    fakebody_buf->last = fakebody_buf->end;
    
    nchan_adjust_subrequest(sr, NGX_HTTP_POST, &POST_REQUEST_STRING, sr_body, sz, NULL);
  }
  else {
    sr->header_only = 1;
  }
  sr->args = sub->request->args;
  
  return sr;
}
Exemple #2
0
static void nchan_publisher_body_handler_continued(ngx_http_request_t *r, ngx_str_t *channel_id, nchan_loc_conf_t *cf) {
  ngx_http_complex_value_t       *publisher_upstream_request_url_ccv;
  static ngx_str_t                POST_REQUEST_STRING = {4, (u_char *)"POST "};
  
  switch(r->method) {
    case NGX_HTTP_GET:
      cf->storage_engine->find_channel(channel_id, (callback_pt) &channel_info_callback, (void *)r);
      break;
    
    case NGX_HTTP_PUT:
    case NGX_HTTP_POST:
      publisher_upstream_request_url_ccv = cf->publisher_upstream_request_url;
      if(publisher_upstream_request_url_ccv == NULL) {
        ngx_str_t    *content_type = (r->headers_in.content_type ? &r->headers_in.content_type->value : NULL);
        ngx_int_t     content_length = r->headers_in.content_length_n > 0 ? r->headers_in.content_length_n : 0;
        
        nchan_publisher_post_request(r, content_type, content_length, r->request_body->bufs, channel_id, cf);
      }
      else {
        nchan_pub_upstream_stuff_t    *psr_stuff;
        
        if((psr_stuff = ngx_palloc(r->pool, sizeof(*psr_stuff))) == NULL) {
          ERR("can't allocate memory for publisher auth subrequest");
          ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
          return;
        }
        
        ngx_http_post_subrequest_t    *psr = &psr_stuff->psr;
        nchan_pub_upstream_data_t     *psrd = &psr_stuff->psr_data;
        ngx_http_request_t            *sr;
        ngx_str_t                      publisher_upstream_request_url;
        
        ngx_http_complex_value(r, publisher_upstream_request_url_ccv, &publisher_upstream_request_url);
        
        psr->handler = nchan_publisher_upstream_handler;
        psr->data = psrd;
        
        psrd->ch_id = channel_id;
        
        ngx_http_subrequest(r, &publisher_upstream_request_url, NULL, &sr, psr, NGX_HTTP_SUBREQUEST_IN_MEMORY);
        nchan_adjust_subrequest(sr, NGX_HTTP_POST, &POST_REQUEST_STRING, r->request_body, r->headers_in.content_length_n, NULL);
      }
      break;
      
    case NGX_HTTP_DELETE:
      cf->storage_engine->delete_channel(channel_id, (callback_pt) &channel_info_callback, (void *)r);
      nchan_maybe_send_channel_event_message(r, CHAN_DELETE);
      break;
      
    default: 
      nchan_respond_status(r, NGX_HTTP_FORBIDDEN, NULL, 0);
  }
  
}
Exemple #3
0
static ngx_int_t websocket_publish(full_subscriber_t *fsub, ngx_buf_t *buf) {
  static ngx_str_t         nopublishing = ngx_string("Publishing not allowed.");
  static ngx_str_t         POST_REQUEST_STRING = {4, (u_char *)"POST "};
  
  if(!fsub->sub.cf->pub.websocket) {
    return websocket_send_close_frame(fsub, CLOSE_POLICY_VIOLATION, &nopublishing);
  }
  
#if (NGX_DEBUG_POOL)
  ERR("ws request pool size: %V", ngx_http_debug_pool_str(fsub->sub.request->pool));
#endif
  
  ngx_http_complex_value_t        *publisher_upstream_request_url_ccv;
  
  publisher_upstream_request_url_ccv = fsub->sub.cf->publisher_upstream_request_url;
  if(publisher_upstream_request_url_ccv == NULL) {
    websocket_publish_continue(fsub, buf);
  }
  else {
    nchan_pub_upstream_stuff_t    *psr_stuff;
    ngx_http_post_subrequest_t    *psr;
    nchan_pub_upstream_data_t     *psrd;
    ngx_http_request_t            *r = fsub->sub.request;
    ngx_http_request_t            *sr;
    ngx_http_request_body_t       *fakebody;
    ngx_chain_t                   *fakebody_chain;
    ngx_buf_t                     *fakebody_buf;
    size_t                         sz;
    
    if(!fsub->upstream_stuff) {
      
      if((psr_stuff = ngx_palloc(r->pool, sizeof(*psr_stuff))) == NULL) {
        ERR("can't allocate memory for publisher auth subrequest");
        websocket_respond_status(&fsub->sub, NGX_HTTP_INTERNAL_SERVER_ERROR, NULL);
        return NGX_ERROR;
      }
      
      fsub->upstream_stuff = psr_stuff;
      psr = &psr_stuff->psr;
      psr->data = &psr_stuff->psr_data;
      psr->handler = websocket_publisher_upstream_handler;
      psr_stuff->psr_data.fsub = fsub;
      
      psr_stuff->psr_data.tmp_pool = NULL;
      
      ngx_http_complex_value(r, publisher_upstream_request_url_ccv, &psr_stuff->psr_data.upstream_request_url); 
    }
    
    psrd = &fsub->upstream_stuff->psr_data;
    psr = &fsub->upstream_stuff->psr;
    
    if(psrd->tmp_pool) {
      //previous upstream request's pool
      ngx_destroy_pool(psrd->tmp_pool);
      psrd->tmp_pool = NULL;
    }
    
    psrd->buf = *buf;
    psrd->original_pool = r->pool;
    psrd->original_cleanup = r->cleanup;
    r->cleanup = NULL;
    
    psrd->tmp_pool = ngx_create_pool(NCHAN_WS_UPSTREAM_TMP_POOL_SIZE, r->connection->log);
    
    r->pool = psrd->tmp_pool;
    //ERR("request %p tmp pool %p", r, r->pool);
    
    fakebody = ngx_pcalloc(r->pool, sizeof(*fakebody));
    if(ngx_buf_size(buf) > 0) {
      fakebody_chain = ngx_palloc(r->pool, sizeof(*fakebody_chain));
      fakebody_buf = ngx_palloc(r->pool, sizeof(*fakebody_buf));
      fakebody->bufs = fakebody_chain;
      fakebody_chain->next = NULL;
      fakebody_chain->buf = fakebody_buf;
      init_msg_buf(fakebody_buf);
      
      //just copy the buffer contents. it's inefficient but I don't care at the moment.
      //this can and should be optimized later
      sz = ngx_buf_size(buf);
      fakebody_buf->start = ngx_palloc(r->pool, sz); //huuh?
      ngx_memcpy(fakebody_buf->start, buf->start, sz);
      fakebody_buf->end = fakebody_buf->start + sz;
      fakebody_buf->pos = fakebody_buf->start;
      fakebody_buf->last = fakebody_buf->end;
    }
    else {
      sz = 0;
    }
    
    ngx_http_subrequest(r, &psrd->upstream_request_url, NULL, &sr, psr, NGX_HTTP_SUBREQUEST_IN_MEMORY);
    nchan_adjust_subrequest(sr, NGX_HTTP_POST, &POST_REQUEST_STRING, fakebody, sz, NULL);
    
    /*
    //http request sudden close cleanup
    if((psrd->cln = ngx_http_cleanup_add(sr, 0)) == NULL) {
      ERR("Unable to add request cleanup for websocket upstream request");
      return NGX_ERROR;
    }
    psrd->cln->data = fsub;
    psrd->cln->handler = (ngx_http_cleanup_pt )sudden_upstream_request_abort_handler;
    */
  }
  
  return NGX_OK;
}