摘要
本文概要介紹使用Nginx上傳模組搭配後端程式mini_httpd進行檔案上傳。
本文
承前,基於Nginx上傳模組與mini_httpd套件,令前者作為反向代理伺服器(reverse proxy)、並使用後者作為後端程式,以處理上傳完畢的後續動作。
修改Nginx組態設置,於上傳完畢時轉向至後端程式;留意location參數、和proxy_pass參數。
建構mini_httpd套件、並編輯組態設置;留意port參數、cgipat參數、及套件版本。
wget https://acme.com/software/mini_httpd/mini_httpd-1.27.tar.gz --no-check-certificate
tar -zxvf mini_httpd-1.27.tar.gz
cd mini_httpd-1.27
make
sudo make install
sudo mkdir -p /web/html
sudo chmod a+rw /web/
sudo echo -e "nochroot\nuser=root\nport=8081\ndir=/web/html\ncgipat=**.cgi\npidfile=/web/mini_httpd.pid\nlogfile=/web/mini_httpd.log\ncharset=UTF-8\n" > /web/mini_httpd.conf
sudo /usr/local/sbin/mini_httpd -C /web/mini_httpd.conf
撰寫基於mini_httpd的CGI程式upload.c,如下,以便於POST上傳結束後呈現相關資訊;留意各個參數係透過STDIN、和環境變數取得,以及解析參數時的識別字串。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> static int traverse_parameter(char* str, int sz, const char* fmt) { if(NULL == str || 0 == sz || NULL == fmt) { return -1; } const char* PATT1 = "Content-Disposition: form-data; name=\""; size_t len_patt1 = strlen(PATT1); const char* PATT2 = "\"\r\n\r\n"; size_t len_patt2 = strlen(PATT2); const char* PATT3 = "\r\n--------------------------"; size_t len_patt3 = strlen(PATT3); char* p1 = NULL; char* p2 = NULL; char* p3 = NULL; p1 = strstr(str, PATT1); int err = (NULL == p1)?(-1):(0); while(NULL != p1) { p2 = strstr(p1 + len_patt1, PATT2); if(NULL != p2) { p3 = strstr(p2 + len_patt2, PATT3); if(NULL != p3) { char k[64] = {'\0'}; memcpy(k, p1 + len_patt1, p2 - (p1 + len_patt1)); char v[256] = {'\0'}; memcpy(v, p2 + len_patt2, p3 - (p2 + len_patt2)); printf(fmt, k, v); p1 = strstr(p3 + len_patt3, PATT1); } else { err = -1; break; } } else { err = -1; break; } } return err; } int main(void) { printf("Content-type: application/json; charset=utf-8\n"); printf("\n\n"); printf("{\n"); printf("\"HTTP_USER_AGENT\": \"%s\",\n", getenv("HTTP_USER_AGENT")); printf("\"REQUEST_METHOD\": \"%s\",\n", getenv("REQUEST_METHOD")); char* query_str = getenv("QUERY_STRING"); if(NULL != query_str) { printf("\"QUERY_STRING\": \"%s\",\n", query_str); } char* c_l_str = getenv("CONTENT_LENGTH"); if(NULL != c_l_str) { printf("\"CONTENT_LENGTH\": \"%s\",\n", c_l_str); char parameter_str[2048] = {'\0'}; int parameter_sz = atoi(c_l_str); (void)fread(parameter_str, parameter_sz, sizeof(char), stdin); const char* fmt_kvp = "\"%s\": \"%s\",\n"; (void)traverse_parameter(parameter_str, parameter_sz, fmt_kvp); } printf("\"HTTP_HOST\": \"%s\",\n", getenv("HTTP_HOST")); printf("\"REMOTE_ADDR\": \"%s\",\n", getenv("REMOTE_ADDR")); printf("}\n"); return EXIT_SUCCESS; } |
建構前述的CGI程式,並且擺放至組態設置所指定的目錄。
gcc -o upload.cgi upload.c
sudo cp upload.cgi /web/html/
因應組態設置來分別執行Nginx與mini_httpd。
使用curl進行檔案上傳測試;可以POST、且會接收到上傳檔案的相關資訊;留意JSON格式編排的各個鍵值對(key-value pair)。
完成。
參考文獻
https://www.796t.com/content/1549294049.html
https://bingbig.github.io/gossip/cURL_multipart_form-data.html
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
https://www.w3.org/Security/Faq/wwwsf4.html
https://blog.csdn.net/sidemap/article/details/101750798
沒有留言:
張貼留言