Skip to content

Commit cd119da

Browse files
committed
feat(websocket): Add websocket HTTP redirect
- Handle 301 status (moved permanently) and redirect the connection to the new host.
1 parent 39e2333 commit cd119da

File tree

1 file changed

+44
-13
lines changed

1 file changed

+44
-13
lines changed

components/esp_websocket_client/esp_websocket_client.c

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ static const char *TAG = "websocket_client";
6464
#define WS_OVER_TCP_SCHEME "ws"
6565
#define WS_OVER_TLS_SCHEME "wss"
6666
#define WS_HTTP_BASIC_AUTH "Basic "
67+
#define WS_HTTP_REDIRECT(code) ((code >= 300) && (code < 400))
68+
69+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
70+
// Features supported in 5.5.0
71+
#define WS_TRANSPORT_REDIRECT_HEADER_SUPPORT 1
72+
#endif
6773

6874
const static int STOPPED_BIT = BIT0;
6975
const static int CLOSE_FRAME_SENT_BIT = BIT1; // Indicates that a close frame was sent by the client
@@ -598,6 +604,23 @@ static esp_err_t esp_websocket_client_create_transport(esp_websocket_client_hand
598604
return ESP_OK;
599605
}
600606

607+
static void esp_websocket_client_prepare_transport(esp_websocket_client_handle_t client)
608+
{
609+
//get transport by scheme
610+
if (client->transport == NULL && client->config->ext_transport == NULL) {
611+
client->transport = esp_transport_list_get_transport(client->transport_list, client->config->scheme);
612+
}
613+
614+
if (client->transport == NULL) {
615+
ESP_LOGE(TAG, "There are no transports valid, stop websocket client");
616+
client->run = false;
617+
}
618+
//default port
619+
if (client->config->port == 0) {
620+
client->config->port = esp_transport_get_default_port(client->transport);
621+
}
622+
}
623+
601624
static int esp_websocket_client_send_with_exact_opcode(esp_websocket_client_handle_t client, ws_transport_opcodes_t opcode, const uint8_t *data, int len, TickType_t timeout)
602625
{
603626
int ret = -1;
@@ -1022,19 +1045,7 @@ static void esp_websocket_client_task(void *pv)
10221045
esp_websocket_client_handle_t client = (esp_websocket_client_handle_t) pv;
10231046
client->run = true;
10241047

1025-
//get transport by scheme
1026-
if (client->transport == NULL && client->config->ext_transport == NULL) {
1027-
client->transport = esp_transport_list_get_transport(client->transport_list, client->config->scheme);
1028-
}
1029-
1030-
if (client->transport == NULL) {
1031-
ESP_LOGE(TAG, "There are no transports valid, stop websocket client");
1032-
client->run = false;
1033-
}
1034-
//default port
1035-
if (client->config->port == 0) {
1036-
client->config->port = esp_transport_get_default_port(client->transport);
1037-
}
1048+
esp_websocket_client_prepare_transport(client);
10381049

10391050
client->state = WEBSOCKET_STATE_INIT;
10401051
xEventGroupClearBits(client->status_bits, STOPPED_BIT | CLOSE_FRAME_SENT_BIT);
@@ -1072,6 +1083,26 @@ static void esp_websocket_client_task(void *pv)
10721083
esp_websocket_client_abort_connection(client, WEBSOCKET_ERROR_TYPE_TCP_TRANSPORT);
10731084
break;
10741085
}
1086+
#if WS_TRANSPORT_REDIRECT_HEADER_SUPPORT
1087+
else if (WS_HTTP_REDIRECT(result)) {
1088+
const char *redir = esp_transport_ws_get_redir_uri(client->transport);
1089+
if (redir) {
1090+
// Redirecting to a new URI
1091+
free(client->config->uri);
1092+
1093+
client->config->uri = strdup(redir);
1094+
client->config->port = 0;
1095+
1096+
esp_websocket_client_set_uri(client, client->config->uri);
1097+
esp_websocket_client_prepare_transport(client);
1098+
1099+
// Rerun the connection with the redir uri.
1100+
client->state = WEBSOCKET_STATE_INIT;
1101+
ESP_LOGI(TAG, "Redirecting to %s", client->config->uri);
1102+
break;
1103+
}
1104+
}
1105+
#endif
10751106
ESP_LOGD(TAG, "Transport connected to %s://%s:%d", client->config->scheme, client->config->host, client->config->port);
10761107

10771108
client->state = WEBSOCKET_STATE_CONNECTED;

0 commit comments

Comments
 (0)