ithewei 4 năm trước cách đây
mục cha
commit
a796305ec2
4 tập tin đã thay đổi với 80 bổ sung19 xóa
  1. 59 13
      examples/curl.cpp
  2. 15 0
      examples/http_client_test.cpp
  3. 4 4
      http/HttpMessage.cpp
  4. 2 2
      http/HttpMessage.h

+ 59 - 13
examples/curl.cpp

@@ -47,36 +47,44 @@ static const char* help = R"(Options:
     -v|--verbose        Show verbose infomation.
     -X|--method         Set http method.
     -H|--header         Add http headers, -H "Content-Type:application/json Accept:*/*"
-    -r|--range          Add http header Range: bytes=0-1023
+    -r|--range          Add http header Range:bytes=0-1023
     -d|--data           Set http body.
-    -F|--form           Set http form, -F "name1=content;name2=@filename"
+    -F|--form           Set http form, -F "name1=content name2=@filename"
     -n|--count          Send request count, used for test keep-alive
        --http2          Use http2
        --grpc           Use grpc over http2
 Examples:
+    curl -v GET  httpbin.org/get
+    curl -v POST httpbin.org/post   user=admin pswd=123456
+    curl -v PUT  httpbin.org/put    user=admin pswd=123456
     curl -v localhost:8080
-    curl -v localhost:8080 -X HEAD
     curl -v localhost:8080 -r 0-9
     curl -v localhost:8080/ping
-    curl -v localhost:8080/query?page_no=1&page_size=10
-    curl -v localhost:8080/echo  -d 'hello,world!'
-    curl -v localhost:8080/kv    -H "Content-Type:application/x-www-form-urlencoded" -d 'user=admin&pswd=123456'
-    curl -v localhost:8080/json  -H "Content-Type:application/json"                  -d '{"user":"admin","pswd":"123456"}'
-    curl -v localhost:8080/form  -F 'file=@filename'
+    curl -v localhost:8080/query?page_no=1\&page_size=10
+    curl -v localhost:8080/echo     hello,world!
+    curl -v localhost:8080/kv       user=admin\&pswd=123456
+    curl -v localhost:8080/json     user=admin pswd=123456
+    curl -v localhost:8080/form     -F file=@filename
 )";
 
-void print_usage() {
-    printf("Usage: curl [%s] url\n", options);
+static void print_usage() {
+    printf("Usage: curl [%s] [METHOD] url [header_field:header_value] [body_key=body_value]\n", options);
 }
-void print_version() {
+static void print_version() {
     printf("curl version 1.0.0\n");
 }
-void print_help() {
+static void print_help() {
     print_usage();
     puts(help);
     print_version();
 }
 
+static bool is_upper_string(const char* str) {
+    const char* p = str;
+    while (*p >= 'A' && *p <= 'Z') ++p;
+    return *p == '\0';
+}
+
 int parse_cmdline(int argc, char* argv[]) {
     int opt;
     int opt_idx;
@@ -100,7 +108,11 @@ int parse_cmdline(int argc, char* argv[]) {
         print_usage();
         exit(-1);
     }
-    url = argv[optind];
+
+    if (is_upper_string(argv[optind])) {
+        method = argv[optind++];
+    }
+    url = argv[optind++];
 
     return 0;
 }
@@ -222,6 +234,40 @@ int main(int argc, char* argv[]) {
             }
         }
     }
+    for (int d = optind; d < argc; ++d) {
+        const char* arg = argv[d];
+        const char* pos = NULL;
+        if ((pos = strchr(arg, ':')) != NULL) {
+            // header_field:header_value
+            *(char*)pos = '\0';
+            req.headers[arg] = pos + 1;
+        } else {
+            if (method == NULL) {
+                req.method = HTTP_POST;
+            }
+            if ((pos = strchr(arg, '&')) != NULL) {
+                if (req.ContentType() == CONTENT_TYPE_NONE) {
+                    req.content_type = X_WWW_FORM_URLENCODED;
+                }
+                req.body = arg;
+            }
+            else if ((pos = strchr(arg, '=')) != NULL) {
+                // body_key=body_value
+                if (req.ContentType() == CONTENT_TYPE_NONE) {
+                    req.content_type = APPLICATION_JSON;
+                }
+                *(char*)pos = '\0';
+                req.Set(arg, pos + 1);
+            }
+            else {
+                if (req.ContentType() == CONTENT_TYPE_NONE) {
+                    req.content_type = TEXT_PLAIN;
+                }
+                req.body = arg;
+            }
+        }
+    }
+
     HttpResponse res;
     /*
     res.head_cb = [](const http_headers& headers){

+ 15 - 0
examples/http_client_test.cpp

@@ -63,6 +63,7 @@ static void test_requests() {
         printf("%s\n", resp->body.c_str());
     }
 
+    // Content-Type: application/json
     hv::Json jroot;
     jroot["user"] = "admin";
     jroot["pswd"] = "123456";
@@ -76,6 +77,20 @@ static void test_requests() {
         printf("%s\n", resp->body.c_str());
     }
 
+    // Content-Type: multipart/form-data
+    requests::Request req(new HttpRequest);
+    req->method = HTTP_POST;
+    req->url = "http://127.0.0.1:8080/echo";
+    req->form["username"] = FormData("admin");
+    req->form["avata"] = FormFile("avatar.jpg");
+    resp = requests::request(req);
+    if (resp == NULL) {
+        printf("request failed!\n");
+    } else {
+        printf("%d %s\r\n", resp->status_code, resp->status_message());
+        printf("%s\n", resp->body.c_str());
+    }
+
     // async
     /*
     int finished = 0;

+ 4 - 4
http/HttpMessage.cpp

@@ -91,7 +91,7 @@ std::string HttpCookie::dump() const {
 // NOTE: json ignore number/string, 123/"123"
 
 std::string HttpMessage::GetString(const char* key, const std::string& defvalue) {
-    switch (content_type) {
+    switch (ContentType()) {
     case APPLICATION_JSON:
     {
         if (!json.is_object()) {
@@ -140,7 +140,7 @@ std::string HttpMessage::GetString(const char* key, const std::string& defvalue)
 
 template<>
 HV_EXPORT int64_t HttpMessage::Get(const char* key, int64_t defvalue) {
-    if (content_type == APPLICATION_JSON) {
+    if (ContentType() == APPLICATION_JSON) {
         if (!json.is_object()) {
             return defvalue;
         }
@@ -176,7 +176,7 @@ HV_EXPORT int HttpMessage::Get(const char* key, int defvalue) {
 
 template<>
 HV_EXPORT double HttpMessage::Get(const char* key, double defvalue) {
-    if (content_type == APPLICATION_JSON) {
+    if (ContentType() == APPLICATION_JSON) {
         if (!json.is_object()) {
             return defvalue;
         }
@@ -208,7 +208,7 @@ HV_EXPORT float HttpMessage::Get(const char* key, float defvalue) {
 
 template<>
 HV_EXPORT bool HttpMessage::Get(const char* key, bool defvalue) {
-    if (content_type == APPLICATION_JSON) {
+    if (ContentType() == APPLICATION_JSON) {
         if (!json.is_object()) {
             return defvalue;
         }

+ 2 - 2
http/HttpMessage.h

@@ -112,7 +112,7 @@ public:
 
     template<typename T>
     void Set(const char* key, const T& value) {
-        switch (content_type) {
+        switch (ContentType()) {
         case APPLICATION_JSON:
             json[key] = value;
             break;
@@ -157,7 +157,7 @@ public:
     }
 
     int SaveFormFile(const char* name, const char* path) {
-        if (content_type != MULTIPART_FORM_DATA) {
+        if (ContentType() != MULTIPART_FORM_DATA) {
             return HTTP_STATUS_BAD_REQUEST;
         }
         const FormData& formdata = form[name];