Robiem co mogę aby ułatwiać ludziom wejście do świata espidf ale czasami ręce mi opadają. Niektóre rzeczy, takie jak zmiana IP, serwery DNS można zrobić za pomocą jednej linijki w #arduino IDE, za to w esp-idf wymaga to wielkiego zachodu. W dodatku na Internecie brak jest przykładów, a dokumentacja jest niewystarczająco czytelna. Podzielę się z wami jak obsłużyć CORS - czyli to z czym będziecie musieli się zmagać, jak zaczniecie używać swojego #esp32 jako serwera http, czyli jakby się wydawało bardzo pospolity use-case. Aż dziwne że nie ma do tego przykładów.
Czym jest CORS?
CORS (Cross-Origin Resource Sharing) to mechanizm, który umożliwia bezpieczne udostępnianie zasobów między stronami internetowymi pochodzącymi z różnych domen.
Należy pamiętać że 192.168.0.1/ oraz 192.168.0.1/endpoint to dwie różne domeny i po próbie wysłania czegoś z klienta(przeglądarki) na endpoint serwera(esp-ka) napotkacie się na błąd CORS.
W nomenklaturze frameworku Arduino problem ten można rozwiązać po prostu wywołując na instancji serwera metodę server.enableCORS(true), przed jego uruchomieniem(co wygooglujecie w minutę). Zauważycie wtedy że lecą jakieś dziwne requesty HTTP_OPTIONS, serwer odpowie jakimiś dziwnymi nagłówkami ale to zignorujecie bo wszystko będzie działać. I dobrze.
W esp-idf musicie te wszystkie rzeczy obsłużyć sami. Przed próbą wysłania HTTP_POST na serwer, przeglądarka wyśle na Wasz endpoint 192.168.0.1/endpoint zapytanie HTTP_OPTIONS na które musicie odpowiedzieć. Wystarczy umieścić w odpowiedzi 3 headery. Przykładowy handler obsługujący corsa.
static esp_err_t cors_handler(httpd_req_t *req)
{
ESP_LOGI(TAG,"OPTIONS cors handler");
httpd_resp_set_hdr(req,"Access-Control-Allow-Headers","*");
httpd_resp_set_hdr(req,"Access-Control-Allow-Origin","*");
httpd_resp_set_hdr(req,"Access-Control-Allow-Methods","*");
httpd_resp_send(req,"",HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
<br />
Dopiero po tej odpowiedzi przyjdzie właściwe zapytanie typu POST z danymi, które chcecie obsłużyć. Jak pod wpisem będzie 5 piorunów do napisze minimalistyczną apke(przykład) która będzie hostowała jakąś stronkę zbierającą dane i wysyłającą je do esp-ka
#programowanie #elektronika #raspberrypi
23991c85-70cd-4ada-8c47-7064673c0e33
RolnikSamWdolinie

"Należy pamiętać że 192.168.0.1/ oraz 192.168.0.1/endpoint to dwie różne domeny"


że niby od kiedy?? To ta sama domena z inną ścieżką

Gitler

@RolnikSamWdolinie jeśli mamy się czepiać słówek to tutaj w ogóle nie ma domeny. Tylko andres IP, domyślny port 80 i endpoint. 192.168.0.1:80 to origin. Jednak żeby uniknąć błędu CORS nie tylko origin musi się zgadzać ale również endpoint, co może być mylące bo CO z CORS to cross origin

PanPaweuDrugi

@Gitler ale przecież przeglądarka nie zgłosi w tym przypadku błędu CORS, musi się różnić domena (adres IP) albo chociaż port. Query string może być dowolny. Aż to dzisiaj sprawdzę.

Gitler

@PanPaweuDrugi owszem. Firefox i google chrome zgłaszają cors

PanPaweuDrugi

@Gitler a na jakiej podstawie przeglądarka blokuje zapytanie pochodzące z tego samego origina? Bo query string nie jest częścią origina.

cec

A nie wystarczy 5 piorunów nad wpisem? ( ͡° ͜ʖ ͡°)

Szanuję za podejście niskopoziomowe, kiedyś szukałem jakiegoś tutoriala do ESP8266, który by pokazywał jak to oprogramować po prostu w C, to wszędzie wyszukiwało tylko to jebane arduino albo inne node JS

Gitler

@cec wystarczy. Co prawda ja pisze w C++ ale w tej apce nie musi być żadnych elementów C++

tellet

@Gitler Dobrze że to robisz, bo dokumentacja do wielu płytek to jest pieprzone dno i metr mułu, gdzie tak naprawdę 90% informacji to kolejne iteracje blink'a albo "to zadziała tylko przy wykorzystaniu konkretnego podzespołu a w przeciwnym wypadku wybuchnie Ci w twarz"

Klopsztanga

@Gitler brak przykładów? uzywales chatgpt?

Gitler

@Klopsztanga w tym przypadku nie. Ale słabo sobie radzie w embeded. Każ mu napisać np. captive portal to się przekonasz

Meverth

@Gitler mało bezpiecznie jest udostępniać * origin. Nagłówek Access-Control-Allow-Origin powinien wskazywać wyłącznie na twoją zaufaną domenę (w tym przypadku IP).

Gitler

@Meverth zgadza się. Jednak cała komunikacji jest w sieci prywatnej dlatego pozwoliłem sobie na taką nonszalancje

LondoMollari

@Gitler Jesteś pewien, że tu Cię CORS zablokował między jednym podkatalogiem w http://192.168.0.1 a drugim też http://192.168.0.1, a nie rozjechało się coś innego? To wg specyfikacji powinno matchować po całym ORIGINie (czyli protokół + adres/domena + port), a to z tego co piszesz był identyczne. Query string czy parametry getowe nie mają znaczenia dla CORSa.


Identyczny setup jak to co opisałeś mam w swoich projektach, i działa bez corsa. CORS generalnie jest po to, jeśli udostępniasz jakieś API na zewnętrzne serwisy, na jednym esp32 to totalny overkill.


Może tak for fun ustaw sobie w hostsach 192.168.0.1 na domenę exp32.lan i zobaczyć co się stanie jak tak otworzysz. Może masz zaszyty jakiś link bezwzględny ze złym adresem?


Reasumując - jeśli strona, z której idzie request na http://192.168.0.1/ to cokolwiek innego niż http://192.168.0.1/, to CORS jest potrzebny, jeśli są identyczne, to CORS nie powinien być wymagany.

Gitler

@LondoMollari Masz racje. Niedopatrzenie w mojej strony. W przypadku który opisujesz nie będzie błędu cors. Jednak kiedy hostujemy stronke na serwerze esp i wysyłamy coś do niej z klienta w tej samej sieci to adresy IP są inne, stad błąd cors. Dodam sprostowanie

LondoMollari

@Gitler Nie jestem pewien czy dobrze rozumiem, dlatego dopytam, ilustrując przykładem:


  • klient: to zawsze będzie przeglądarka, którą otwierasz swoją aplikację webową, powiedzmy z IP 192.168.0.100, ale to tutaj kompletnie nie ma znaczenia

  • serwer 1 (np. na jakimś PCcie czy RaspberryPI): 192.168.0.10 - tutaj stoi właściwa aplikacja webowa, javascripty, statyczne pliki, style css, etc, etc.

  • serwer 2 (na esp32): 192.168.0.20 - tutaj jest Twój webservice napisany w esp-idf


Jeśli teraz jest tak, że klient wchodzi na adres 192.168.0.10 a następnie javascripty wysyłają requesty XHR do esp32 pod adresem 192.168.0.20, to TAK - CORS będzie niezbędny, żeby JS mógł tak bezpośrednio odpytywać.


Jeśli klient wchodzi tylko i wyłącznie na adres 192.168.0.20, serwer pod 192.168.0.10 w ogóle nie istnieje, a wszystkie JSy i wszystkie elementy portalu są pobierane ze 192.168.0.20, to NIE, CORS nie powinien być potrzebny. Jeśli CORS jest wtedy wymagany, to coś jest tutaj prawdopodobnie popsute.

Meverth

@Gitler tylko Twoi czytelnicy tego nie wiedzą. Będą bezmyślnie kopiować, doprowadzając do dziur bezpieczeństwa. Nie każdy się przejmuje bezpieczeństwem, nie każdy rozumie. W ogóle im bezpieczniej, tym trudniej a juniorom się nie chce, jak kiedyś...

ZohanTSW

Można tagować #embedded

Vuaaas

@Gitler Nie zgodziłbym się że server http na esp to pospolity use-case. Pospolitym use-casem jest to że esp jest klientem i przesyła dane na serwer, albo że esp jest serwerem i komunikuje się z klientem za pomocą socketów TCP/UDP. Serwer http to jakiś overkill na zasadzie prześlemy obrazek z kamerki, ale i tak nie podłączy się pod to więcej niż jedna osoba w tym samym momencie.

SUQ-MADIQ

@Gitler dawaj wincy tego mięsa o esp32

Zaloguj się aby komentować