Răsfoiți Sursa

httpd: use HTTP status 303 for setlang

303 is "See other"; it is the proper code for "this isn't the resource
you requested, this is "what follows".
H. Peter Anvin 2 ani în urmă
părinte
comite
2a2e4a901a
4 a modificat fișierele cu 52 adăugiri și 24 ștergeri
  1. 52 24
      esp32/max80/httpd.c
  2. BIN
      esp32/output/max80.ino.bin
  3. BIN
      fpga/output/v1.fw
  4. BIN
      fpga/output/v2.fw

+ 52 - 24
esp32/max80/httpd.c

@@ -144,7 +144,8 @@ static const char text_plain[] = "text/plain; charset=\"UTF-8\"";
 enum hsp_flags {
     HSP_CLOSE        = 1,
     HSP_CRLF         = 2,
-    HSP_CLOSE_SOCKET = 4
+    HSP_CLOSE_SOCKET = 4,
+    HSP_REFERER      = 8	/* Use referer as body (for redirects) */
 };
 
 static void httpd_print_request(const httpd_req_t *req)
@@ -152,6 +153,22 @@ static void httpd_print_request(const httpd_req_t *req)
     printf("[HTTP] %s %s\n", http_method_str(req->method), req->uri);
 }
 
+static char *httpd_req_get_hdr(httpd_req_t *req, const char *field, size_t *lenp)
+{
+    size_t len = httpd_req_get_hdr_value_len(req, field);
+    char *val  = NULL;
+    if (len) {
+	val = malloc(len+1);
+	if (val) {
+	    httpd_req_get_hdr_value_str(req, field, val, len+1);
+	    val[len] = '\0';
+	}
+    }
+    if (lenp)
+	*lenp = len;
+    return val;
+}
+
 static esp_err_t httpd_send_plain(httpd_req_t *req,
 				  unsigned int rcode,
 				  const char *body, size_t blen,
@@ -170,30 +187,33 @@ static esp_err_t httpd_send_plain(httpd_req_t *req,
     const char *closer = flags & HSP_CLOSE ? "Connection: close\r\n" : "";
     bool redirect = rcode >= 300 && rcode <= 399;
 
-    char *refresher = (char *)"";
-    if (refresh) {
-	size_t referer_length = httpd_req_get_hdr_value_len(req, "Referer");
-	const size_t refhdrsize = sizeof("Refresh: ;url=") +
-	    3*sizeof(unsigned int);
-	refresher = malloc(refhdrsize + referer_length + 4);
-	if (!refresher) {
-	    refresher = (char *)"";
-	} else {
-	    size_t rlen = snprintf(refresher, refhdrsize,
-				   "Refresh: %u;url=", refresh);
-	    if (referer_length) {
-		httpd_req_get_hdr_value_str(req, "Referer", refresher+rlen,
-					    referer_length+1);
-		rlen += referer_length;
-	    } else {
-		refresher[rlen++] = '/';
-	    }
-	    memcpy(refresher+rlen, "\r\n", 3);
+    char *referer = NULL;
+    char *refresher_buf = NULL;
+
+    if (refresh || (flags & HSP_REFERER)) {
+	size_t referer_len;
+	referer = httpd_req_get_hdr(req, "Referer", &referer_len);
+
+	/* "Effective" referer */
+	const char * const ereferer = referer ? referer : "/";
+
+	if (refresh) {
+	    asprintf(&refresher_buf, "Refresh: %u;url=%s\r\n",
+		     refresh, ereferer);
+	}
+	if (flags & HSP_REFERER) {
+	    body = ereferer;
+	    blen = referer ? referer_len : 1;
 	}
     }
 
+    const char * const refresher = refresher_buf ? refresher_buf : "";
+
     if (redirect) {
-	size_t blenadj = sizeof("3xx Redirect \r"); /* \0 -> \n so don't include it */
+	/* \0 -> \n so don't include it */
+	size_t blenadj = sizeof("3xx Redirect \r");
+
+	/* Always CR LF */
 	flags |= HSP_CRLF;
 
 	/* Drop any CR LF already in the redirect string */
@@ -230,8 +250,11 @@ static esp_err_t httpd_send_plain(httpd_req_t *req,
 			closer, refresher);
     }
 
-    if (*refresher)
-	free(refresher);
+    if (refresher_buf)
+	free(refresher_buf);
+
+    if (referer)
+	free(referer);
 
     if (!header)
 	return ESP_ERR_NO_MEM;
@@ -354,7 +377,12 @@ static esp_err_t httpd_set_lang(httpd_req_t *req, const char *query)
 	read_config(NULL, true);	/* Save configuration */
     }
 
-    return httpd_send_plain(req, 200, SL("Language set"), HSP_CRLF, 1);
+    /*
+     * 303 = "See other": proper return code saying "this is not what
+     * you asked for, this is *about* what you asked for"; see spec
+     * but this is exactly what we want here.
+     */
+    return httpd_send_plain(req, 303, NULL, 0, HSP_REFERER, 0);
 }
 
 static esp_err_t httpd_get_lang(httpd_req_t *req)

BIN
esp32/output/max80.ino.bin


BIN
fpga/output/v1.fw


BIN
fpga/output/v2.fw