update 2026-09-24 16:56:26

This commit is contained in:
action committed 2026-09-24 16:56:26 +08:00
1 parent b31a5c3878
commit e4cee331e9
6885 files changed
+3240523

No files matched your search

@@ -0,0 +1,24 @@
Copyright (C) 2016-2020, by Jie Wu "AlexWoo" <wj19840501@gmail.com>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
@@ -0,0 +1,19 @@
ngx_addon_name=ngx_client_module
CORE_MODULES="$CORE_MODULES \
ngx_client_module \
ngx_http_client_module \
"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
$ngx_addon_dir/ngx_client.c \
$ngx_addon_dir/ngx_http_client.c \
"
NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
$ngx_addon_dir/ngx_client.h \
$ngx_addon_dir/ngx_http_client.h \
"
CFLAGS="$CFLAGS -I $ngx_addon_dir"
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,165 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_CLIENT_H_INCLUDED_
#define _NGX_CLIENT_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_http.h>
typedef struct ngx_client_session_s ngx_client_session_t;
typedef void (* ngx_client_connect_pt)(ngx_client_session_t *s);
typedef void (* ngx_client_recv_pt)(ngx_client_session_t *s);
typedef void (* ngx_client_send_pt)(ngx_client_session_t *s);
typedef void (* ngx_client_closed_pt)(ngx_client_session_t *s);
struct ngx_client_session_s {
ngx_peer_connection_t peer;
ngx_str_t server; /* server original address */
in_port_t port; /* server port */
ngx_connection_t *connection;
ngx_pool_t *pool;
ngx_log_t log;
void *data; /* save ctx for callback */
ngx_chain_t *out; /* save data unsend */
/* configured part */
/* timer for connecting to server */
ngx_msec_t connect_timeout;
/* timer for sending buffer full */
ngx_msec_t send_timeout;
/*
* data will be postponed until nginx has at least
* postpone_output bytes of data to send
*/
size_t postpone_output;
/* use dynamic resolver mechanism for resolving domain */
unsigned dynamic_resolver:1;
unsigned tcp_nodelay:1; /* TCP_NODELAY */
unsigned tcp_nopush:1; /* TCP_CORK */
/* runtime part */
size_t recv; /* client recv bytes */
unsigned connected:1; /* client connected to server */
unsigned closed:1; /* client has been closed */
ngx_event_t close; /* for async close */
/* callback */
ngx_client_connect_pt client_connected; /* connect successd */
ngx_client_recv_pt client_recv; /* recv msg from peer */
ngx_client_send_pt client_send; /* send msg to peer */
ngx_client_closed_pt client_closed; /* finalize connection */
};
/*
* create a client session
*
* return value:
* return client session for successd, return NULL for failed
* paras:
* peer: server address and port, address could be domain or ip
* local: set if need to bind local address, or set NULL
* udp: set 1, use udp, set 0, use tcp
* log: for logging error when create client session failed
*/
ngx_client_session_t *ngx_client_create(ngx_str_t *peer, ngx_str_t *local,
ngx_flag_t udp, ngx_log_t *log);
/*
* connect to client server, should use client session created by
* ngx_client_create. before connect to server, user can set paras in
* configured part.
*
* return value:
* void
* paras:
* s: client session created by ngx_client_create
*/
void ngx_client_connect(ngx_client_session_t *s);
/*
* send data to server
*
* return value:
* NGX_ERROR: write error, client session will be closed
* NGX_AGAIN: data not sent completely, it will save in client session out
* NGX_OK: data sent completely
* paras:
* s: client session
* out: data for sending
*/
ngx_int_t ngx_client_write(ngx_client_session_t *s, ngx_chain_t *out);
/*
* read data from server
*
* return value:
* NGX_ERROR: read error, client session will be closed
* NGX_DECLINED: buf for receiving data is full
* NGX_AGAIN: no data for reading
* 0: server closed
* >0: bytes read into buffer
* paras:
* s: client session
* b: buffer for receiving data
*/
ngx_int_t ngx_client_read(ngx_client_session_t *s, ngx_buf_t *b);
/*
* keepalive client connection, and destroy session
* if use client connect the same ip:port,
* new client session will reuse the connection
*
* return value:
* void
* paras:
* s: client session
*/
void ngx_client_set_keepalive(ngx_client_session_t *s);
/*
* close client session
*
* return value:
* void
* paras:
* s: client session
*/
void ngx_client_close(ngx_client_session_t *s);
/*
* paras:
* r: http request to query status of client
*/
ngx_chain_t *ngx_client_state(ngx_http_request_t *r, unsigned detail);
#endif
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,323 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#ifndef _NGX_HTTP_CLIENT_H_INCLUDE_
#define _NGX_HTTP_CLIENT_H_INCLUDE_
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_client.h"
#include "ngx_toolkit_misc.h"
// http client method
#define NGX_HTTP_CLIENT_GET 0
#define NGX_HTTP_CLIENT_HEAD 1
#define NGX_HTTP_CLIENT_POST 2
#define NGX_HTTP_CLIENT_PUT 3
#define NGX_HTTP_CLIENT_DELETE 4
#define NGX_HTTP_CLIENT_MKCOL 5
#define NGX_HTTP_CLIENT_COPY 6
#define NGX_HTTP_CLIENT_MOVE 7
#define NGX_HTTP_CLIENT_OPTIONS 8
#define NGX_HTTP_CLIENT_PROPFIND 9
#define NGX_HTTP_CLIENT_PROPPATCH 10
#define NGX_HTTP_CLIENT_LOCK 11
#define NGX_HTTP_CLIENT_UNLOCK 12
#define NGX_HTTP_CLIENT_PATCH 13
#define NGX_HTTP_CLIENT_TRACE 14
// http client version
#define NGX_HTTP_CLIENT_VERSION_9 0
#define NGX_HTTP_CLIENT_VERSION_10 1
#define NGX_HTTP_CLIENT_VERSION_11 2
#define NGX_HTTP_CLIENT_VERSION_20 3
// http client opt
#define NGX_HTTP_CLIENT_OPT_CONNECT_TIMEOUT 0
#define NGX_HTTP_CLIENT_OPT_SEND_TIMEOUT 1
#define NGX_HTTP_CLIENT_OPT_POSTPONE_OUTPUT 2
#define NGX_HTTP_CLIENT_OPT_DYNAMIC_RESOLVER 3
#define NGX_HTTP_CLIENT_OPT_TCP_NODELAY 4
#define NGX_HTTP_CLIENT_OPT_TCP_NOPUSH 5
#define NGX_HTTP_CLIENT_OPT_HEADER_TIMEOUT 6
typedef void (* ngx_http_client_handler_pt)(void *r, ngx_http_request_t *hcr);
/* create and set http request */
/*
* create a http request for sending to server
*
* return value:
* return http request for successd, return NULL for failed
*
* paras:
* log: error in create will use this log
* method: http client method
* url: full request url like "http://test.com/index.html?hello=world"
* headers: http request header for sending
* send_body: callback for sending body
* request: who send http request
*/
ngx_http_request_t *ngx_http_client_create(ngx_log_t *log,
ngx_uint_t method, ngx_str_t *url, ngx_keyval_t *headers,
ngx_http_client_handler_pt send_body, void *request);
/*
* add cleanup as ngx_http_cleanup_add
*/
ngx_http_cleanup_t *ngx_http_client_cleanup_add(ngx_http_request_t *r,
size_t size);
/*
* set read handler for http client, should set before send request,
* otherwise body from server will discard
*
* return value:
* void
*
* paras:
* r: http client request
* read_handler: handler for setting
*/
void ngx_http_client_set_read_handler(ngx_http_request_t *r,
ngx_http_client_handler_pt read_handler);
/*
* set http headers
*
* return value:
* NGX_OK for successd, NGX_ERROR for failed
*
* paras:
* r: http client request
* headers: headers set into r
* if value is not null, will set or modify the header
* if value is null string, will delete the header
*/
ngx_int_t ngx_http_client_set_headers(ngx_http_request_t *r,
ngx_keyval_t *headers);
/*
* set write handler for http client, if set,
* will use this handler for sending body,
*
* return value:
* void
*
* paras:
* r: http client request
* write_handler: handler for setting
*/
void ngx_http_client_set_write_handler(ngx_http_request_t *r,
ngx_http_client_handler_pt write_handler);
/*
* set write handler for http client, if set,
* will use this handler for sending body,
*
* return value:
* void
*
* paras:
* r: http client request
* write_handler: handler for setting
*/
void ngx_http_client_set_version(ngx_http_request_t *r, ngx_uint_t version);
/*
* set http client option
*
* return value:
* void
*
* paras:
* r: http client request
* opt: http client opt
* NGX_HTTP_CLIENT_OPT_CONNECT_TIMEOUT:
* connect server timer
* NGX_HTTP_CLIENT_OPT_SEND_TIMEOUT:
* send data timer when buffer full
* NGX_HTTP_CLIENT_OPT_POSTPONE_OUTPUT:
* size threshold to send
* NGX_HTTP_CLIENT_OPT_DYNAMIC_RESOLVER:
* whether use dynamic resolver to resolv domain
* NGX_HTTP_CLIENT_OPT_TCP_NODELAY:
* whether set TCP_NODELAY
* NGX_HTTP_CLIENT_OPT_TCP_NOPUSH:
* whether set TCP_CORK
* NGX_HTTP_CLIENT_OPT_HEADER_TIMEOUT:
* timer for waiting response header from server
* value: http client opt value want to set
*/
void ngx_http_client_setopt(ngx_http_request_t *r, unsigned opt,
ngx_uint_t value);
/* send http request */
/*
* send http request
*
* return value:
* NGX_OK for successd, NGX_ERROR for failed
*
* paras:
* r: http request for seding, create by ngx_http_client_create
*/
ngx_int_t ngx_http_client_send(ngx_http_request_t *r);
/*
* create and send http GET request to server
*
* return value:
* return http request for successd, return NULL for failed
*
* paras:
* log: error in create will use this log
* url: full request url like "http://test.com/index.html?hello=world"
* headers: http request header for sending
* request: who send http request
*/
ngx_http_request_t *ngx_http_client_get(ngx_log_t *log, ngx_str_t *url,
ngx_keyval_t *headers, void *request);
/*
* create and send http HEAD request to server
*
* return value:
* return http request for successd, return NULL for failed
*
* paras:
* log: error in create will use this log
* url: full request url like "http://test.com/index.html?hello=world"
* headers: http request header for sending
* request: who send http request
*/
ngx_http_request_t *ngx_http_client_head(ngx_log_t *log, ngx_str_t *url,
ngx_keyval_t *headers, void *request);
/*
* create and send http POST request to server
*
* return value:
* return http request for successd, return NULL for failed
*
* paras:
* log: error in create will use this log
* url: full request url like "http://test.com/index.html?hello=world"
* headers: http request header for sending
* send_body: callback for sending body
* request: who send http request
*/
ngx_http_request_t *ngx_http_client_post(ngx_log_t *log, ngx_str_t *url,
ngx_keyval_t *headers, ngx_http_client_handler_pt send_body, void *request);
/* get response */
/*
* get http response version
*
* return value:
* http response version
*
* paras:
* r: http client request
*/
ngx_uint_t ngx_http_client_http_version(ngx_http_request_t *r);
/*
* get http response status code
*
* return value:
* http response status code like 200, 500
*
* paras:
* r: http client request
*/
ngx_uint_t ngx_http_client_status_code(ngx_http_request_t *r);
/*
* get http response header's value
*
* return value:
* http response header's value
*
* paras:
* r: http client request
* key: http header like "Host", "Content-Type"
*/
ngx_str_t *ngx_http_client_header_in(ngx_http_request_t *r, ngx_str_t *key);
/*
* read http response body
*
* return value:
* NGX_AGAIN: read part of data
* 0: tcp connection disconnect, need finalize request with 1
* NGX_ERROR: tcp connection error disconnect, need finalize request with 1
* NGX_DONE: response body has been read, could finalize request with 0
*
* paras:
* r: http client request
* in: where read data put
*/
ngx_int_t ngx_http_client_read_body(ngx_http_request_t *r, ngx_chain_t **in);
/*
* get receive bytes
*
* return value:
* bytes receive from server
*
* paras:
* r: http client request
*/
off_t ngx_http_client_rbytes(ngx_http_request_t *r);
/*
* get send bytes
*
* return value:
* bytes send to server
*
* paras:
* r: http client request
*/
off_t ngx_http_client_wbytes(ngx_http_request_t *r);
/* end request */
/*
* detach http client request with it's creator,
* all read and write handler will not be triggered
*
* return value:
* bytes send to server
*
* paras:
* r: http client request
*/
void ngx_http_client_detach(ngx_http_request_t *r);
/*
* finalize http client request
*
* return value:
* void
*
* paras:
* r: http client request
* closed: set to 1, will close connection to server
* set to 0, will keep connection to server alive
*/
void ngx_http_client_finalize_request(ngx_http_request_t *r, ngx_flag_t closed);
#endif
@@ -0,0 +1,13 @@
ngx_addon_name=ngx_client_test_module
HTTP_MODULES="$HTTP_MODULES \
ngx_client_test_module \
ngx_http_client_test_module \
ngx_client_stat_module \
"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS
$ngx_addon_dir/ngx_client_test_module.c \
$ngx_addon_dir/ngx_http_client_test_module.c \
$ngx_addon_dir/ngx_client_stat_module.c \
"
@@ -0,0 +1,57 @@
user root;
worker_processes 4;
#error_log logs/error.log;
#error_log logs/error.log notice;
error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
resolver 192.168.84.254;
dynamic_refresh_interval 5m;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /client_test {
client_test;
}
location /http_client_test {
http_client_test;
}
location /client_stat {
client_stat;
}
}
}
@@ -0,0 +1,148 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_http.h>
#include "ngx_client.h"
#include "ngx_rbuf.h"
#include "ngx_poold.h"
#include "ngx_timerd.h"
#include "ngx_event_timer_module.h"
#include "ngx_event_resolver.h"
#include "ngx_dynamic_resolver.h"
static char *ngx_client_stat(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_client_stat_commands[] = {
{ ngx_string("client_stat"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_client_stat,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_client_stat_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_client_stat_module = {
NGX_MODULE_V1,
&ngx_client_stat_module_ctx, /* module context */
ngx_client_stat_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
};
static ngx_int_t
ngx_client_stat_handler(ngx_http_request_t *r)
{
ngx_chain_t **ll, *out;
ngx_buf_t *b;
size_t len;
r->headers_out.status = NGX_HTTP_OK;
ngx_http_send_header(r);
ll = &out;
len = sizeof("--------------------------------------------------\n") - 1
+ sizeof("ngx_worker: ngx_process_slot: pid: \n") - 1
+ 3 * NGX_OFF_T_LEN;
*ll = ngx_alloc_chain_link(r->pool);
if (*ll == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
(*ll)->next = NULL;
b = ngx_create_temp_buf(r->pool, len);
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
(*ll)->buf = b;
b->last = ngx_snprintf(b->last, len,
"--------------------------------------------------\n"
"ngx_worker: %i ngx_process_slot: %i pid: %i\n",
ngx_worker, ngx_process_slot, ngx_pid);
if (*ll) {
ll = &(*ll)->next;
}
*ll = ngx_rbuf_state(r, 1);
if (*ll) {
ll = &(*ll)->next;
}
*ll = ngx_event_timer_state(r);
if (*ll) {
ll = &(*ll)->next;
}
*ll = ngx_event_resolver_state(r);
if (*ll) {
ll = &(*ll)->next;
}
*ll = ngx_dynamic_resolver_state(r);
if (*ll) {
ll = &(*ll)->next;
}
*ll = ngx_poold_state(r, 1);
if (*ll) {
ll = &(*ll)->next;
}
*ll = ngx_timerd_state(r, 1);
if (*ll) {
ll = &(*ll)->next;
}
*ll = ngx_client_state(r, 1);
(*ll)->buf->last_buf = 1;
return ngx_http_output_filter(r, out);
}
static char *
ngx_client_stat(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);
clcf->handler = ngx_client_stat_handler;
return NGX_CONF_OK;
}
@@ -0,0 +1,188 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include "ngx_client.h"
static char *ngx_client_test(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_client_test_commands[] = {
{ ngx_string("client_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_client_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_client_test_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_client_test_module = {
NGX_MODULE_V1,
&ngx_client_test_module_ctx, /* module context */
ngx_client_test_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
};
static void
ngx_client_test_connected(ngx_client_session_t *s)
{
ngx_buf_t *b;
size_t len;
ngx_chain_t out;
ngx_http_request_t *r;
ngx_event_t *wev;
ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client connected");
r = s->data;
wev = s->peer.connection->write;
len = sizeof("nginx client test\n") - 1;
b = ngx_create_temp_buf(s->pool, len);
if (b == NULL) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
b->last = ngx_copy(b->last, "nginx client test\n", len);
b->last_buf = 1;
out.buf = b;
out.next = NULL;
ngx_client_write(s, &out);
ngx_handle_write_event(wev, 0);
}
static void
ngx_client_test_recv(ngx_client_session_t *s)
{
ngx_buf_t *b;
ngx_int_t n;
ngx_connection_t *c;
ngx_str_t recv;
ngx_http_request_t *r;
c = s->peer.connection;
r = s->data;
b = ngx_create_temp_buf(s->pool, 4096);
if (b == NULL) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
n = c->recv(c, b->pos, b->end - b->last);
if (n == NGX_AGAIN) {
ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client recv NGX_AGAIN");
return;
}
if (n == NGX_ERROR || n == 0) {
ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client recv NGX_ERROR");
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
ngx_client_close(s);
return;
}
b->last += n;
recv.data = b->pos;
recv.len = b->last - b->pos;
ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client recv %d: %V, %z",
n, &recv, recv.len);
ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
ngx_client_set_keepalive(s);
return;
}
static void
ngx_client_test_send(ngx_client_session_t *s)
{
ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client send");
}
static void
ngx_client_test_closed(ngx_client_session_t *s)
{
ngx_log_error(NGX_LOG_ERR, &s->log, 0, "client closed");
}
static ngx_int_t
ngx_client_test_handler(ngx_http_request_t *r)
{
ngx_client_session_t *s;
ngx_str_t echo;
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client test handler");
if (ngx_http_arg(r, (u_char *) "echo", sizeof("echo") - 1, &echo)
!= NGX_OK)
{
return NGX_HTTP_BAD_REQUEST;
}
s = ngx_client_create(&echo, NULL, 0, r->connection->log);
if (s == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
//ci->dynamic_resolver = 0;
//ci->recvbuf = 4096;
s->client_connected = ngx_client_test_connected;
s->client_recv = ngx_client_test_recv;
s->client_send = ngx_client_test_send;
s->client_closed = ngx_client_test_closed;
s->data = r;
ngx_client_connect(s);
++r->count;
return NGX_DONE;
}
static char *
ngx_client_test(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);
clcf->handler = ngx_client_test_handler;
return NGX_CONF_OK;
}
@@ -0,0 +1,203 @@
/*
* Copyright (C) AlexWoo(Wu Jie) wj19840501@gmail.com
*/
#include "ngx_http_client.h"
#include "ngx_rbuf.h"
static char *ngx_http_client_test(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_command_t ngx_http_client_test_commands[] = {
{ ngx_string("http_client_test"),
NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
ngx_http_client_test,
0,
0,
NULL },
ngx_null_command
};
static ngx_http_module_t ngx_http_client_test_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_client_test_module = {
NGX_MODULE_V1,
&ngx_http_client_test_module_ctx, /* module context */
ngx_http_client_test_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
};
static void
ngx_http_client_test_recv_body(void *request, ngx_http_request_t *hcr)
{
ngx_http_request_t *r;
ngx_chain_t *cl = NULL;
ngx_chain_t **ll;
ngx_int_t rc;
r = request;
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"http client test recv body");
rc = ngx_http_client_read_body(hcr, &cl);
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"http client test recv body, rc %i %i, %O",
rc, ngx_errno, ngx_http_client_rbytes(hcr));
if (rc == 0) {
goto done;
}
if (rc == NGX_ERROR) {
goto done;
}
if (rc == NGX_DONE) {
for (ll = &cl; (*ll)->next; ll = &(*ll)->next);
(*ll)->buf->last_buf = 1;
}
ngx_http_output_filter(r, cl);
ngx_http_run_posted_requests(r->connection);
if (rc == NGX_AGAIN) {
return;
}
if (rc == NGX_DONE) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"all body has been read");
ngx_http_client_finalize_request(hcr, 0);
}
done:
ngx_http_finalize_request(r, NGX_OK);
}
static void
ngx_http_client_test_recv(void *request, ngx_http_request_t *hcr)
{
ngx_http_request_t *r;
static ngx_str_t content_type = ngx_string("Content-Type");
static ngx_str_t connection = ngx_string("Connection");
static ngx_str_t unknown = ngx_string("Unknown");
ngx_str_t *ct, *con;
r = request;
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"http client test recv, connection: %p", hcr->connection);
r->headers_out.status = 200;
ngx_http_client_set_read_handler(hcr, ngx_http_client_test_recv_body);
ngx_http_send_header(r);
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"status_code: %ui http_version: %ui",
ngx_http_client_status_code(hcr),
ngx_http_client_http_version(hcr));
ct = ngx_http_client_header_in(hcr, &content_type);
con = ngx_http_client_header_in(hcr, &connection);
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "Content-Type: %V", ct);
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "Connection: %V", con);
if (ngx_http_client_header_in(hcr, &unknown) == NULL) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "no header Unknown");
}
ngx_http_client_test_recv_body(request, hcr);
}
static ngx_int_t
ngx_http_client_test_handler(ngx_http_request_t *r)
{
ngx_http_request_t *hcr;
static ngx_str_t request_url = ngx_string("http://101.200.241.232/");
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"http client test handler");
// Default header Host, User-Agent, Connection(below HTTP/1.1), Accept, Date
hcr = ngx_http_client_create(r->connection->log, NGX_HTTP_CLIENT_GET,
&request_url, NULL, NULL, r);
// add Connection, delete Date, Modify Host, add new header
ngx_str_t value;
value.data = (u_char *) "World";
value.len = sizeof("World") - 1;
ngx_keyval_t headers[] = {
{ ngx_string("Host"), ngx_string("www.test.com") },
{ ngx_string("Connection"), ngx_string("upgrade") },
{ ngx_string("Date"), ngx_null_string },
{ ngx_string("Hello"), value },
{ ngx_null_string, ngx_null_string } // must end with null str
};
ngx_http_client_set_headers(hcr, headers);
ngx_http_client_set_read_handler(hcr, ngx_http_client_test_recv);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"http client test before send");
ngx_http_client_send(hcr);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"http client test after send");
// ngx_http_client_detach(hcr);
// return NGX_HTTP_FORBIDDEN;
++r->count;
return NGX_DONE;
}
static char *
ngx_http_client_test(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);
clcf->handler = ngx_http_client_test_handler;
return NGX_CONF_OK;
}
@@ -0,0 +1,41 @@
package main
import (
"fmt"
"net"
)
func handleConnection(c net.Conn) {
b := make([]byte, 4096)
for {
n, err := c.Read(b)
if err != nil {
fmt.Print("Read Error ", err)
c.Close()
return
}
fmt.Print("recv ", n, " data:", string(b))
c.Write(b[0:n])
}
}
func main() {
ln, err := net.Listen("tcp", ":10000")
if err != nil {
fmt.Print("Listen Error ", err)
return
}
for {
conn, err := ln.Accept()
if err != nil {
fmt.Print("Accept Error ", err)
continue
}
go handleConnection(conn)
}
}