Last active
December 5, 2016 14:46
-
-
Save defanator/cf040a46a98bb681c6148a9ee614eb70 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
http { | |
location /samples { | |
sample; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment