client.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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]; /* Host name from command line */
  33. opt.port = 443; /* Default HTTPS port */
  34. opt.client_cert = NULL; /* Client certificate, if required */
  35. opt.server_cert = NULL; /* Server certificate to verify */
  36. opt.host_name = opt.host; /* Host name for SNI */
  37. struct mg_connection *cli =
  38. mg_connect_client_secure(&opt, errbuf, sizeof(errbuf));
  39. /* Check return value: */
  40. if (cli == NULL) {
  41. fprintf(stderr, "Cannot connect client: %s\n", errbuf);
  42. return EXIT_FAILURE;
  43. }
  44. printf("cli: %p\n", cli);
  45. mg_printf(cli, "GET / HTTP/1.1\r\n");
  46. mg_printf(cli, "Host: %s\r\n", opt.host);
  47. mg_printf(cli, "Connection: close\r\n\r\n");
  48. int ret = mg_get_response(cli, errbuf, sizeof(errbuf), 10000);
  49. if (ret < 0) {
  50. fprintf(stderr, "Download failed: %s\n", errbuf);
  51. mg_close_connection(cli);
  52. return EXIT_FAILURE;
  53. }
  54. const struct mg_response_info *ri = mg_get_response_info(cli);
  55. if (ri == NULL) {
  56. fprintf(stderr, "mg_response_info failed\n");
  57. mg_close_connection(cli);
  58. return EXIT_FAILURE;
  59. }
  60. printf("Status: %i %s\n", ri->status_code, ri->status_text);
  61. printf("HTTP Version: %s\n", ri->http_version);
  62. printf("Content-Length: %lli\n", ri->content_length);
  63. printf("Headers:\n");
  64. int is_chunked = 0;
  65. for (int i = 0; i < ri->num_headers; i++) {
  66. printf(" %s: %s\n",
  67. ri->http_headers[i].name,
  68. ri->http_headers[i].value);
  69. if (!strcasecmp(ri->http_headers[i].name, "Transfer-Encoding")
  70. && !strcasecmp(ri->http_headers[i].value, "chunked")) {
  71. is_chunked = 1;
  72. }
  73. }
  74. long long cont = ri->content_length;
  75. if (cont > 0) {
  76. /* Read regular content */
  77. printf("Content:\n");
  78. while (cont > 0) {
  79. char buf[1024];
  80. int ret = mg_read(cli, buf, sizeof(buf));
  81. if (ret <= 0) {
  82. printf("read error\n");
  83. break;
  84. }
  85. cont -= ret;
  86. fwrite(buf, 1, ret, stdout);
  87. }
  88. } else {
  89. /* Read chunked content (or content without content length) */
  90. char buf[1024];
  91. for (;;) {
  92. int ret = mg_read(cli, buf, sizeof(buf));
  93. if (ret <= 0)
  94. break;
  95. fwrite(buf, 1, ret, stdout);
  96. }
  97. }
  98. mg_close_connection(cli);
  99. return EXIT_SUCCESS;
  100. }