Hejto.pl
Dodaj post

Wpisz coś do wyszukania (minimum 2 znaki)

Wpis użytkownika Gitler w Programowanie

Inspirator

w Programowanie

58piorunów

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  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  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;

}

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

Komentarze (20)

Autorytet1piorunów

@Gitler dawaj wincy tego mięsa o esp32

Mocarz3piorunów

@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.

Gruba ryba0piorunów

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

Zawodowiec1piorunów

@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ś...

Fanatyk0piorunów

@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.

Inspirator0piorunów

@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

Fanatyk0piorunów

@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.

Inspirator0piorunów

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

Zawodowiec2piorunów

@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).

Inspirator0piorunów

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

Kosmonauta3piorunów

@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"

Osobistość1piorunów

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

Inspirator0piorunów

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

Kompan8piorunów

"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ą

Wirtuoz0piorunów

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

Inspirator1piorunów

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

Wirtuoz3piorunów

@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ę.

Inspirator6piorunów

@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

Wirtuoz0piorunów

Zadziwiające