IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> nginx实现subrequest子请求 -> 正文阅读

[系统运维]nginx实现subrequest子请求

1.ngx_http_mytest_module.c


/*
 * Copyright (C) Maxim Dounin
 */


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>


typedef struct {
  ngx_str_t     response_json;   //注意这里尽量定义成nginx支持的类型,否则赋值时可能出现问题
} ngx_http_mytest_ctx_t;


static char *ngx_http_mytest(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t mytest_subrequest_post_handler(ngx_http_request_t *r, void *data, ngx_int_t rc);
static void mytest_post_handler(ngx_http_request_t *r);
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r);

static ngx_command_t  ngx_http_mytest_commands[] = {

    { ngx_string("mytest"),
      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
      ngx_http_mytest,
      NGX_HTTP_LOC_CONF_OFFSET,
      0,
      NULL },

      ngx_null_command
};


static ngx_http_module_t  ngx_http_mytest_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_mytest_module = {
    NGX_MODULE_V1,
    &ngx_http_mytest_module_ctx,     /* module context */
    ngx_http_mytest_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 char *
ngx_http_mytest(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_mytest_handler;

    return NGX_CONF_OK;
}

/*子请求结束时的处理方法*/
static ngx_int_t mytest_subrequest_post_handler(ngx_http_request_t *r, void *data, ngx_int_t rc)
{
    ngx_http_request_t *pr = r->parent;     //当前请求的r是子请求,parent指向父请求
    ngx_http_mytest_ctx_t* myctx = ngx_http_get_module_ctx(pr,ngx_http_mytest_module);  //获取父请求的上下文

    pr->headers_out.status = r->headers_out.status;


    if(r->headers_out.status == NGX_HTTP_OK)    //返回ok意味着子请求访问服务器成功,开始解析返回的HTTP包体
    {
        ngx_buf_t* pRecvBuf = &r->upstream->buffer;

        myctx->response_json.data = pRecvBuf->pos;
        myctx->response_json.len  = pRecvBuf->last - pRecvBuf->pos; //接收返回数据

    }

    pr->write_event_handler = mytest_post_handler;          //注册父请求回调函数

    return NGX_OK;
}

//父请求处理方法
static void mytest_post_handler(ngx_http_request_t *r)
{
    if(r->headers_out.status != NGX_HTTP_OK)    //如果没有返回200,则直接把错误码发回用户
    {
        ngx_http_finalize_request(r, r->headers_out.status);
        return;
    }

    ngx_http_mytest_ctx_t* myctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module);  //取上下文

    ngx_str_t output_format = ngx_string("大家好我是%V"); //定义发送给用户的HTTP包体内容

    int bodylen = output_format.len + myctx->response_json.len - 2; //计算包体长度

    //在内存池上分配内存,保存要发送的包体
    ngx_buf_t* b = ngx_create_temp_buf(r->pool, bodylen);
    ngx_snprintf(b->pos, bodylen, (char*)output_format.data, &myctx->response_json);
    b->last = b->pos + bodylen;
    b->last_buf = 1;

    ngx_chain_t out;
    out.buf = b;
    out.next = NULL;

    static ngx_str_t type = ngx_string("text/plain");   //设置返回字体
    r->headers_out.content_type = type;
    r->headers_out.status       = NGX_HTTP_OK;

    r->connection->buffered |= NGX_HTTP_WRITE_BUFFERED;
    ngx_int_t ret = ngx_http_send_header(r);
    ret = ngx_http_output_filter(r, &out);

    ngx_http_finalize_request(r, ret);  //注意这里必须手动调用函数结束请求,因为这时HTTP框架不会再帮助调用它

}


//启动subrequest
static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t *r)
{
    //创建HTTP上下文
    ngx_http_mytest_ctx_t* myctx = ngx_http_get_module_ctx(r, ngx_http_mytest_module);
    if(myctx == NULL)
    {
        myctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mytest_ctx_t));
        if(myctx == NULL)
        {
            return NGX_ERROR;
        }

        //将上下文设置到原始请求r中
        ngx_http_set_ctx(r,myctx,ngx_http_mytest_module);
    }

    //创建子请求结构体
    ngx_http_post_subrequest_t *psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
    if(psr == NULL)
    {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    psr->handler = mytest_subrequest_post_handler;  //设置子请求的回调函数为mytest_subrequest_post_handler

    psr->data = myctx;  //将子请求中的参数data设置为myctx,这样在回调mytest_subrequest_post_handler函数时传入的data参数就是myctx


    /*获取nginx的conf文件中location为list的子请求要转到的ip*/
    ngx_str_t sub_prefix = ngx_string("/list=");
    ngx_str_t sub_location;
    sub_location.len  = sub_prefix.len + r->args.len;
    sub_location.data = ngx_palloc(r->pool, sub_location.len);
    ngx_snprintf(sub_location.data, sub_location.len, "%V%V", &sub_prefix, &r->args);

    //sr就是子请求
    ngx_http_request_t *sr;

    ngx_int_t rc = ngx_http_subrequest(r, &sub_location, NULL, &sr, psr, NGX_HTTP_SUBREQUEST_IN_MEMORY);    //调用函数传入设置的参数,注册子请求,等待HTTP框架处理
    if(rc != NGX_OK)
    {
        return NGX_ERROR;
    }

    return NGX_DONE;    //这里必须返回NGX_DONE

}

2.nginx.conf

.............

server{

????????listen 2222;

? ? ? ?location /mytest {

? ? ? ? ? ? ? ? mytest;

????????}

? ? ? ? location /list {

????????????????proxy_pass http://127.0.0.1:1111/response;

? ? ? ? ? ? ? ? proxy_set_header Accept-Encoding "";? ? ? ? //不压缩返回

????????}

}

3.测试方法:

1)将此nginx服务复制,并修改配置文件如下:

server{

????????listen 1111;

? ? ? ?location /response {

? ? ? ? ? ? ? return 200 'caixukun';

????????}

}

2)将两个服务都启动

3)使用postman访问http://ip:2222/mytest即可得到返回? ? ? ? 大家好我是caixukun

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 02:22:56  更:2022-09-15 02:25:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 20:08:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计