client.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * Copyright (c) 2018 the CivetWeb developers
  3. * MIT License
  4. */
  5. /* Simple client demo. */
  6. #ifdef _WIN32
  7. #include <windows.h>
  8. #else
  9. #include <unistd.h>
  10. #endif
  11. #include <stdarg.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <time.h>
  15. #include "civetweb.h"
  16. int
  17. main(int argc, char *argv[])
  18. {
  19. if (argc < 2) {
  20. fprintf(stderr, "Requires server name as argument\n");
  21. return EXIT_FAILURE;
  22. }
  23. /* Init libcivetweb. */
  24. mg_init_library(MG_FEATURES_TLS);
  25. if (mg_check_feature(MG_FEATURES_TLS) != MG_FEATURES_TLS) {
  26. fprintf(stderr, "TLS is not available\n");
  27. return EXIT_FAILURE;
  28. }
  29. /* Connect client */
  30. char errbuf[256] = {0};
  31. struct mg_client_options opt = {0};
  32. opt.host = argv[1];
  33. opt.port = 443;
  34. struct mg_connection *cli =
  35. mg_connect_client_secure(&opt, errbuf, sizeof(errbuf));
  36. /* Check return value: */
  37. if (cli == NULL) {
  38. fprintf(stderr, "Cannot connect client: %s\n", errbuf);
  39. return EXIT_FAILURE;
  40. }
  41. printf("cli: %p\n", cli);
  42. mg_printf(cli, "GET / HTTP/1.1\r\n");
  43. mg_printf(cli, "Host: %s\r\n", opt.host);
  44. mg_printf(cli, "Connection: close\r\n\r\n");
  45. int ret = mg_get_response(cli, errbuf, sizeof(errbuf), 10000);
  46. if (ret < 0) {
  47. fprintf(stderr, "Download failed: %s\n", errbuf);
  48. mg_close_connection(cli);
  49. return EXIT_FAILURE;
  50. }
  51. const struct mg_response_info *ri = mg_get_response_info(cli);
  52. if (ri == NULL) {
  53. fprintf(stderr, "mg_response_info failed\n");
  54. mg_close_connection(cli);
  55. return EXIT_FAILURE;
  56. }
  57. printf("Status: %i %s\n", ri->status_code, ri->status_text);
  58. printf("HTTP Version: %s\n", ri->http_version);
  59. printf("Content-Length: %lli\n", ri->content_length);
  60. printf("Headers:\n");
  61. int is_chunked = 0;
  62. for (int i = 0; i < ri->num_headers; i++) {
  63. printf(" %s: %s\n",
  64. ri->http_headers[i].name,
  65. ri->http_headers[i].value);
  66. if (!strcasecmp(ri->http_headers[i].name, "Transfer-Encoding")
  67. && !strcasecmp(ri->http_headers[i].value, "chunked")) {
  68. is_chunked = 1;
  69. }
  70. }
  71. long long cont = ri->content_length;
  72. if (cont > 0) {
  73. /* Read regular content */
  74. printf("Content:\n");
  75. while (cont > 0) {
  76. char buf[1024];
  77. int ret = mg_read(cli, buf, sizeof(buf));
  78. if (ret <= 0) {
  79. printf("read error\n");
  80. break;
  81. }
  82. cont -= ret;
  83. fwrite(buf, 1, ret, stdout);
  84. }
  85. } else if (is_chunked) {
  86. /* Read chunked content (or content without content length) */
  87. char buf[1024];
  88. for (;;) {
  89. int ret = mg_read(cli, buf, sizeof(buf));
  90. if (ret <= 0)
  91. break;
  92. fwrite(buf, 1, ret, stdout);
  93. }
  94. }
  95. mg_close_connection(cli);
  96. return EXIT_SUCCESS;
  97. }