Looking for a clean HTTP POST example

wevets
Posts: 112
Joined: Sat Mar 09, 2019 2:56 am

Looking for a clean HTTP POST example

Postby wevets » Sat Aug 15, 2020 8:43 pm

I am building an app that needs to do simple HTTP POSTs to a server in the cloud. I have looked at esp-idf http client example and it runs just fine. Then I instrumented it to look only at POSTs and to check the stack, modifying the task code as shown:
  1. static void http_test_task(void *pvParameters)
  2. {
  3.         UBaseType_t StackMargin = uxTaskGetStackHighWaterMark(NULL);
  4.         UBaseType_t MainPriority = uxTaskPriorityGet(NULL);
  5.         printf("The main task stack margin is: %d\r\n", StackMargin);
  6.         printf("Priority of main task is %d\r\n", MainPriority);
  7.        
  8.     http_rest_with_url();
  9.    
  10.         StackMargin = uxTaskGetStackHighWaterMark(NULL);
  11.         MainPriority = uxTaskPriorityGet(NULL);
  12.         printf("The main task stack margin is: %d\r\n", StackMargin);
  13.         printf("Priority of main task is %d\r\n", MainPriority);
  14.    
  15.     http_rest_with_hostname_path();
  16.     // http_auth_basic();
  17.     // http_auth_basic_redirect();
  18.     // http_auth_digest();
  19.     // http_relative_redirect();
  20.     // http_absolute_redirect();
  21.     // https_with_url();
  22.     // https_with_hostname_path();
  23.     // http_redirect_to_https();
  24.     // http_download_chunk();
  25.     // http_perform_as_stream_reader();
  26.     // https_async();
  27.     https_with_invalid_url();
  28.    
  29.         StackMargin = uxTaskGetStackHighWaterMark(NULL);
  30.         MainPriority = uxTaskPriorityGet(NULL);
  31.         printf("The main task stack margin is: %d\r\n", StackMargin);
  32.         printf("Priority of main task is %d\r\n", MainPriority);
  33.  
  34.     ESP_LOGI(TAG, "Finish http example");
  35.     vTaskDelete(NULL);
  36. }
This, of course, builds without error (with a few undefined functions, which I've also commented out to eliminate the warnings). (The SSID of the access point I'm linking to is "FBI Surveillance Van". It seems to keep the riff-raff away). When I run this, I get the following output on the monitor:
  1. <Bunch of bootloader stuff>
  2. I (0) cpu_start: Starting scheduler on APP CPU.
  3. I (654) wifi:wifi driver task: 3ffc2240, prio:23, stack:6656, core=0
  4. I (654) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
  5. I (654) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE
  6. I (684) wifi:wifi firmware version: aa5336b
  7. I (684) wifi:config NVS flash: enabled
  8. I (684) wifi:config nano formating: disabled
  9. I (684) wifi:Init dynamic tx buffer num: 32
  10. I (684) wifi:Init data frame dynamic rx buffer num: 32
  11. I (694) wifi:Init management frame dynamic rx buffer num: 32
  12. I (694) wifi:Init management short buffer num: 32
  13. I (704) wifi:Init static rx buffer size: 1600
  14. I (704) wifi:Init static rx buffer num: 10
  15. I (714) wifi:Init dynamic rx buffer num: 32
  16. I (714) example_connect: Connecting to FBI Surveillance Van...
  17. I (814) phy: phy_version: 4180, cb3948e, Sep 12 2019, 16:39:13, 0, 0
  18. I (824) wifi:mode : sta (8c:aa:b5:85:55:1c)
  19. I (944) wifi:new:<1,0>, old:<1,0>, ap:<255,255>, sta:<1,0>, prof:1
  20. I (1924) wifi:state: init -> auth (b0)
  21. I (1924) wifi:state: auth -> init (8a0)
  22. I (1924) wifi:new:<1,0>, old:<1,0>, ap:<255,255>, sta:<1,0>, prof:1
  23. I (1924) example_connect: Wi-Fi disconnected, trying to reconnect...
  24. I (3984) example_connect: Wi-Fi disconnected, trying to reconnect...
  25. I (4104) wifi:new:<1,0>, old:<1,0>, ap:<255,255>, sta:<1,0>, prof:1
  26. I (4104) wifi:state: init -> auth (b0)
  27. I (4114) wifi:state: auth -> assoc (0)
  28. I (4114) wifi:state: assoc -> run (10)
  29. I (4154) wifi:connected with FBI Surveillance Van, aid = 1, channel 1, BW20, bssid = ec:aa:a0:33:df:b8
  30. I (4154) wifi:security: WPA2-PSK, phy: bgn, rssi: -43
  31. I (4154) wifi:pm start, type: 1
  32.  
  33. I (4204) wifi:AP's beacon interval = 102400 us, DTIM period = 1
  34. I (5144) tcpip_adapter: sta ip: 10.0.0.63, mask: 255.255.255.0, gw: 10.0.0.1
  35. I (5644) example_connect: Connected to FBI Surveillance Van
  36. I (5644) example_connect: IPv4 address: 10.0.0.63
  37. I (5644) example_connect: IPv6 address: fe80:0000:0000:0000:8eaa:b5ff:fe85:551c
  38. I (5654) HTTP_CLIENT: Connected to AP, begin http example
  39. The main task stack margin is: 7888                                               // Look Here
  40. Priority of main task is 5
  41. I (5954) HTTP_CLIENT: HTTP GET Status = 200, content_length = 270
  42. I (6564) HTTP_CLIENT: HTTP POST Status = 200, content_length = 444
  43. I (6564) HTTP_CLIENT: HTTP_EVENT_DISCONNECTED
  44. The main task stack margin is: 6320                                              // Look Here
  45. Priority of main task is 5
  46. I (6874) HTTP_CLIENT: HTTP GET Status = 200, content_length = 270
  47. I (7384) HTTP_CLIENT: HTTP POST Status = 200, content_length = 444
  48. I (7654) HTTP_CLIENT: HTTP PUT Status = 200, content_length = 443
  49. I (7804) HTTP_CLIENT: HTTP PATCH Status = 200, content_length = 335
  50. I (7914) HTTP_CLIENT: HTTP DELETE Status = 200, content_length = 336
  51. I (8104) HTTP_CLIENT: HTTP HEAD Status = 200, content_length = 270
  52. I (8104) HTTP_CLIENT: HTTP_EVENT_DISCONNECTED
  53. E (8204) esp-tls: couldn't get hostname for :not.existent.url:
  54. E (8204) esp-tls: Failed to open new connection
  55. E (8204) TRANS_SSL: Failed to open a new connection
  56. E (8214) HTTP_CLIENT: Connection failed, sock < 0
  57. E (8214) HTTP_CLIENT: Error perform http request ERROR
  58. I (8224) HTTP_CLIENT: HTTP_EVENT_DISCONNECTED
  59. I (8224) HTTP_CLIENT: Last esp error code: 0x8001
  60. I (8234) HTTP_CLIENT: Last mbedtls failure: 0x0
  61. The main task stack margin is: 6096                                             // Look Here
  62. Priority of main task is 5
  63. I (8244) HTTP_CLIENT: Finish http example
There are successful POSTs and GETs (returns codes of 200) from the two routines I call from the test task, and a successful handling of the attempt to link to the "not.existaent.url"

The problem is that all of this eats stack even though the active routines have calls to esp_http_client_cleanup(), which is advertised to return all resources involved in the network transactions.

What am I missing here? And can anyone point me to some code that executes a clean HTTP POST through a WiFi connection that does not eat stack, or a some resource that explains how to properly do the seemingly simple thing I want to do? My application needs to wait until a condition worth POSTing to a network server arises, which might have a period of anywhere between a few minutes to 24 hours. When testing with minimum report periods, I get stack overflows, and that's not good.

Forgive my naivete, but everyone has to start somewhere.

boarchuz
Posts: 566
Joined: Tue Aug 21, 2018 5:28 am

Re: Looking for a clean HTTP POST example

Postby boarchuz » Sat Aug 15, 2020 9:57 pm

The problem is that all of this eats stack
This is fine. That's what it's for. You can expect anything it uses its stack for to be "freed" when out of scope.

The http client will allocate what it needs on the *heap*. This will not affect your task's *stack*. These heap allocations are freed with esp_http_client_cleanup.

You're using uxTaskGetStackHighWaterMark:
https://www.freertos.org/uxTaskGetStack ... rMark.html
Naturally, some execution paths will need more stack memory than others. But only temporarily. It's reset by the time they return to the http_test_task scope. Coincidentally, the particular order here, along with the use of high water mark, might make it seem as if available stack is permanently shrinking (it's not). Putting everything in this task inside an infinite loop should be illustrative, printing free heap mem too.

Actually, uxTaskGetStackHighWaterMark indicates that the task never had below 6k available, so it's surprising that you're having issues with stack overflow. Maybe there's a large buffer that can't fit (eg. char post_data[8192]; char http_response[resp_content_length];)? Perhaps post that code instead.

wevets
Posts: 112
Joined: Sat Mar 09, 2019 2:56 am

Re: Looking for a clean HTTP POST example

Postby wevets » Sat Aug 15, 2020 10:22 pm

Thanks for the quick reply.

The reason I started looking at the sample HTTP client is that I had an implementation based on this client working in my app until.... it crashed with a stack overflow after several HTTP POSTs. I wasn't monitoring stack penetration at that point, I only saw the stack overflow notification. My effort here was to use the example to better understand the behavior of the sample code.

I was under the impression that esp_http_client_cleanup() actually did, as is advertised, release ALL the resources used in a network transaction. I'll go over my code again, as well as trying out your suggestion for monitoring the sample to verify, or not, my results and to make sure that I'm making all the necessary calls in the correct order.

And just to understand, can the example code in the esp-idf HTTP client be used pretty much as is for a production HTTP client that primarily only POSTs to a network target?

Who is online

Users browsing this forum: antonjung, ESP_jakob and 140 guests