1
0

wget.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * @build: make examples
  3. * @server bin/httpd -s restart -d
  4. * @client bin/wget 127.0.0.1:8080/
  5. */
  6. #include "requests.h"
  7. int main(int argc, char** argv) {
  8. if (argc < 2) {
  9. printf("Usage: %s url\n", argv[0]);
  10. }
  11. const char* url = argv[1];
  12. std::string filepath;
  13. const char* path = strrchr(url, '/');
  14. if (path == NULL || path[1] == '\0') {
  15. filepath = "index.html";
  16. } else {
  17. filepath = path + 1;
  18. }
  19. printf("save file to %s ...\n", filepath.c_str());
  20. HFile file;
  21. if (file.open(filepath.c_str(), "wb") != 0) {
  22. fprintf(stderr, "Failed to open file %s\n", filepath.c_str());
  23. return -10;
  24. }
  25. // HEAD
  26. requests::Request req(new HttpRequest);
  27. req->url = url;
  28. req->method = HTTP_HEAD;
  29. printf("%s\n", req->Dump(true, true).c_str());
  30. auto resp = requests::request(req);
  31. if (resp == NULL) {
  32. fprintf(stderr, "request failed!\n");
  33. return -1;
  34. }
  35. printf("%s\n", resp->Dump(true, false).c_str());
  36. bool use_range = false;
  37. int range_bytes = 1 << 20; // 1M
  38. std::string accept_ranges = resp->GetHeader("Accept-Ranges");
  39. size_t content_length = hv::from_string<size_t>(resp->GetHeader("Content-Length"));
  40. // use Range if server accept_ranges and content_length > 1M
  41. if (resp->status_code == 200 &&
  42. accept_ranges == "bytes" &&
  43. content_length > range_bytes) {
  44. use_range = true;
  45. }
  46. // GET
  47. req->method = HTTP_GET;
  48. if (!use_range) {
  49. printf("%s\n", req->Dump(true, true).c_str());
  50. resp = requests::get(url);
  51. if (resp == NULL) {
  52. fprintf(stderr, "request failed!\n");
  53. return -1;
  54. }
  55. printf("%s\n", resp->Dump(true, false).c_str());
  56. file.write(resp->body.data(), resp->body.size());
  57. return 0;
  58. }
  59. // [from, to]
  60. long from, to;
  61. from = 0;
  62. http_client_t* cli = http_client_new();
  63. while (from < content_length) {
  64. to = from + range_bytes - 1;
  65. if (to >= content_length) to = content_length - 1;
  66. // Range: bytes=from-to
  67. req->SetRange(from, to);
  68. printf("%s\n", req->Dump(true, true).c_str());
  69. int ret = http_client_send(cli, req.get(), resp.get());
  70. if (ret != 0) {
  71. fprintf(stderr, "request failed!\n");
  72. return -1;
  73. }
  74. printf("%s\n", resp->Dump(true, false).c_str());
  75. file.write(resp->body.data(), resp->body.size());
  76. from = to + 1;
  77. }
  78. http_client_del(cli);
  79. return 0;
  80. }