Skip to content

Instantly share code, notes, and snippets.

@defanator
Last active December 5, 2016 14:46
Show Gist options
  • Save defanator/cf040a46a98bb681c6148a9ee614eb70 to your computer and use it in GitHub Desktop.
Save defanator/cf040a46a98bb681c6148a9ee614eb70 to your computer and use it in GitHub Desktop.
// from: http://byteandbits.blogspot.ru/2013/08/example-nginx-module-for-reading.html
// see also: http://www.serverphorums.com/read.php?5,79835,79835#msg-79835
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
const char* documentRoot = "/usr/local/nginx/html/";
static void ngx_http_sample_put_handler(ngx_http_request_t *r)
{
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "put handler called");
char filename[200] = { '\0' };
struct timeval tv;
gettimeofday(&tv, NULL);
sprintf(filename, "%s%ld.%ld", documentRoot, tv.tv_sec, tv.tv_usec);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "FileName:%s", filename);
int fd = creat(filename, 0644);
if(-1 == fd)
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to create mail file.%s", strerror(errno));
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
if(NULL == r->request_body->temp_file)
{
/*
* The entire request body is available in the list of buffers pointed by r->request_body->bufs.
*
* The list can have a maixmum of two buffers. One buffer contains the request body that was pre-read along with the request headers.
* The other buffer contains the rest of the request body. The maximum size of the buffer is controlled by 'client_body_buffer_size' directive.
* If the request body cannot be contained within these two buffers, the entire body is writtin to the temp file and the buffers are cleared.
*/
ngx_buf_t *buf;
ngx_chain_t *cl;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Writing data from buffers.");
cl = r->request_body->bufs;
for( ;NULL != cl; cl = cl->next )
{
buf = cl->buf;
if(write(fd, buf->pos, buf->last - buf->pos) < 0)
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer.");
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
close(fd);
return;
}
}
}
else
{
/**
* The entire request body is available in the temporary file.
*
*/
size_t ret;
size_t offset = 0;
unsigned char data[4096];
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Writing data from temp file.");
while( (ret = ngx_read_file(&r->request_body->temp_file->file, data, 4096, offset)) > 0)
{
if(write(fd, data, ret) < 0)
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer.");
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
close(fd);
return;
}
offset = offset + ret;
}
}
close(fd);
unsigned char* data;
data = ngx_pcalloc(r->pool, strlen(filename));
if (data == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer.");
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
ngx_memcpy(data, filename + strlen(documentRoot), strlen(filename) - strlen(documentRoot));
r->headers_out.status = NGX_HTTP_ACCEPTED;
r->headers_out.content_length_n = strlen(filename) - strlen(documentRoot);
r->headers_out.content_type.len = sizeof("text/plain") - 1;
r->headers_out.content_type.data = (u_char *) "text/plain";
r->headers_out.location = ngx_list_push(&r->headers_out.headers);
if (NULL == r->headers_out.location) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
r->headers_out.location->hash = 1;
r->headers_out.location->key.len = sizeof("Location") - 1;
r->headers_out.location->key.data = (u_char *) "Location";
r->headers_out.location->value.len = strlen(filename) - strlen(documentRoot);
r->headers_out.location->value.data = data;
ngx_http_send_header(r);
ngx_int_t rc;
rc = ngx_http_send_header(r);
if(rc == NGX_ERROR || rc > NGX_OK)
{
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Sending headers failed.");
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
ngx_buf_t *b;
ngx_chain_t out;
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (b == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate response buffer.");
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
}
b->pos = data;
b->last = data + (strlen(filename));
b->memory = 1;
b->last_buf = 1;
out.buf = b;
out.next = NULL;
ngx_http_finalize_request(r, ngx_http_output_filter(r, &out));
return;
}
static ngx_int_t
ngx_http_sample_handler(ngx_http_request_t *r)
{
ngx_int_t rc;
/**
* Specify the handler function to be called after reading the request body.
*/
rc = ngx_http_read_client_request_body(r, ngx_http_sample_put_handler);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE){
return rc;
}
return NGX_DONE;
}
static char *
ngx_http_sample(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_core_loc_conf_t *clcf;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
/**
* Get the location configuration and specify the function
* that would hanlde requests for this location.
*/
clcf->handler = ngx_http_sample_handler;
return NGX_CONF_OK;
}
static ngx_command_t ngx_http_sample_commands[] = {
{ ngx_string("sample"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_sample,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_http_sample_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
NULL, /* create location configuration */
NULL /* merge location configuration */
};
ngx_module_t ngx_http_sample_module = {
NGX_MODULE_V1,
&ngx_http_sample_module_ctx, /* module context */
ngx_http_sample_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
http {
location /samples {
sample;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment