Re: [lwip-users] httpd: how to implement AJAX
Il 13/11/2017 21:25, goldsi...@gmx.de ha scritto: Giuseppe Modugno wrote: The prototype for SSI callbacks is: [..] I don't see any reference to query string parameters. So how to select the right action? Sorry for the confusion. This is a mix of resource optimization, missing documentation and maybe missing framework functions. The idea is that we don't want to keep the http request pbuf(s) around until the end of the SSI file is transmitted (which might be long). Instead, this is done in three steps: - fs_open() calls fs_state_init(file, name) to create an object big enough to hold everything you'd need for 'file' (for custom files, you'll have to call this yourself) - httpd_cgi_handler() can parse everything needed and store it in this object - the SSI handler gets this object, too, and can access the content required (- or alternatively, in a custom read function, you might direclty access file->state) I'm trying to implement what you wrote, using "custom files" instead of SSI. I think something doesn't work. Suppose I have a CGI script that the client requests with a *GET /login.cgi?auth=pippo:pluto* fs_open_custom() returns 1 if "login.cgi" is passed as filename. However here I'm not able to create the answer, because I need to evaluate the query string parameters (that I will do in CGI handler). So I can't do much in fs_open_custom() and I don't know how to set file->data, file->line and file->index. In CGI handler I'm ready to create the full answer because I have the query string, maybe in a buffer allocated with malloc and saved in file->state pointer. The problem here is fs_read_custom() is never called, because LWIP_HTTPD_DYNAMIC_FILE_READ isn't defined. Is really needed to define LWIP_HTTPD_DYNAMIC_FILE_READ in this scenario? This macro will allocate a dynamic output buffer in http_state and call fs_read_custom() that will limit to copy all or part of data created in CGI to the buffer of http_state. It seems too complex for this scenario. In CGI handler I could set all the "file info" in http_state (length and pointer), however http_state isn't accessible from this point. One thing I can't understand. It's index member of struct fs_file. It is initialized as the length of file content if fs_open(), for non custom files. And it is used in: int fs_bytes_left(struct fs_file *file) { return file->len - file->index; } So after fs_bytes_left() is zero immediately after fs_open(). This sounds strange to me. Maybe index isn't the pointer to unsent data (it should be zero after open), but to the pointer of the next byte to read from file (and for "static" files, there's no other data to read after open, because all data is ready immediately). ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
Re: [lwip-users] httpd: how to implement AJAX
Il 14/11/2017 13:54, Noam Weissman ha scritto: Hi, HTTPD is widely used and if you look around you can find examples from ST micro TI and other vendors. Do you mean HTTPD *without* a secure layer? Yes, I know there are many examples of it, but IMHO because it is simpler than a full HTTPS server. I don't think you can use a non-secure HTTP (or MQTT or SNMP) communication in a public network today for a serious application that isn't a simple test example. ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
Re: [lwip-users] httpd: how to implement AJAX
Hi, HTTPD is widely used and if you look around you can find examples from ST micro TI and other vendors. The examples that you will find are probably older versions with no POST or AJAX support but they work ! Noam. -Original Message- From: lwip-users [mailto:lwip-users-bounces+noam=silrd@nongnu.org] On Behalf Of Giuseppe Modugno Sent: Tuesday, November 14, 2017 2:47 PM To: lwip-users@nongnu.org Subject: Re: [lwip-users] httpd: how to implement AJAX Il 13/11/2017 21:25, goldsi...@gmx.de ha scritto: > Giuseppe Modugno wrote: >> The prototype for SSI callbacks is: >> [..] >> I don't see any reference to query string parameters. So how to >> select the right action? > > Sorry for the confusion. This is a mix of resource optimization, > missing documentation and maybe missing framework functions. Thank you very much for your explanation. Now it is clear. > My plan is to have https examples for the next release... https would be very interesting (actually a simple non-secure http server isn't really useable in public Internet). If I understood correctly, https means ssl/tls. So the first task is to add SSL/TLS to lwip, right? It's a pity lwip doesn't feature those secure network layers. ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
Re: [lwip-users] httpd: how to implement AJAX
Hi, Yes I use a different server. My server code was based on a variation of the httpd code + many additions. I use POST to send the user+password and no it is not encoded... this is mainly for simple use. The SSID is not a cookie... The SSID's are handles in a separate task that does the house keeping. Regarding the single file trick you may be right but this is how it works for me and I OK with it :) Regarding the GET/POST params... as the server parses the URL it also parses the GET params. BR, Noam. From: lwip-users [mailto:lwip-users-bounces+noam=silrd@nongnu.org] On Behalf Of Giuseppe Modugno Sent: Tuesday, November 14, 2017 2:42 PM To: lwip-users@nongnu.org Subject: Re: [lwip-users] httpd: how to implement AJAX Il 13/11/2017 18:04, Noam Weissman ha scritto: Yes SSID is a session ID that had been added to my own server code. So are you using a completely different HTTP server from the httpd that is in apps folder of lwip main source? When a user askes for a page and there is no ssid the server will redirect (send a 303) And load a login page instead. After the user writes user+password the data is sent to The server. How do you send user+password to the server? PUT? Do you encode these sensible values? The server call's external code to check for validity of user+pass... if OK it Request a new ssid from a separate task. After that the web server sends the previously request page + ssid... every operation at the browser side must add that ssid value. Is it a cookie, right? Every time the web server gets a request with the correct ssid it clears the related timeout. If the ssid timeouts and the user asks for some data it will again redirect to the login page. Do you call a specific function from main at regular intervals to clear all SSID that expire? Regarding AJAX: How do you handle SSI ?... I am doing it differently ? I have something like this in my code: const SSI_t SSI_Table[] = { {"mem_rout", mem_routing}, {"IOSel", IO_Selection}, {"get_users", get_users}, {"ajax_reply", AjaxReply}, {NULL, NULL} // last tag must always be NULL to close the list }; mem_routing, IO_Selection, get_users, and AjaxReply are call-back function that are called by the web server as a result of encountering the proper tag... for mem_routing it is I think LWIP_HTTPD_CUSTOM_FILES is simpler to use when you have a file that is completely dynamic. Your "single tag trick" works, but IMHO is too complex for what you have to do. my AjaxReply parses the GET params and after that does something like that: How AjaxReply() function could access GET params if they aren't accessible from the SSI handler? Most probably the answer is in the file state (LWIP_HTTPD_FILE_STATE) that is filled by httpd_cgi_handler() callback (as explained by goldsimon). // get action param Char *Action = some_function(); If(strcmp(Action, "do_something_1") == 0) { } elses If(strcmp(Action, "do_something_2") == 0) { } else { // print a debug error : action unknown } Hope that helped, Noam. From: lwip-users [mailto:lwip-users-bounces+noam=silrd@nongnu.org] On Behalf Of Giuseppe Modugno Sent: Monday, November 13, 2017 6:09 PM To: lwip-users@nongnu.org<mailto:lwip-users@nongnu.org> Subject: Re: [lwip-users] httpd: how to implement AJAX Il 13/11/2017 14:34, Noam Weissman ha scritto: Hi, I am using the following technic for AJAX. Create an empty file named ajax.shtml or ajax.html and add it to your file list. Inside the file you only write one tag without anything else. For example Do not add CR or LF just the tag !!. Now when you issue an AJAX call the WEB server opens the file, reads it and send its data. Because the file has only the tag it will parse it, call your handler for that tag and send back To the browser just your data !! Ok, so you use SSI to create dynamic data. I tried with custom files, because *all the content* is dynamic (and not only some parts, defined by specific tags). If you use Juery it will look something like this... actually a function used as an event handler in my own code: function resetIO() { //Remove the dialog returnToPage(); $.ajax({ url: "ajax.shtml", dataType : "text", type : "GET", cache : false, data : ({ ssid: ssid, a: 'opReset', type: 2 }), error : function() { showMessage("Network Error: Sorry, there was a problem connecting to the server."); }, success : function(result) { window.location.href = document.location; } }); } In the above data you have the a: variable, this is your AJAX action !. If I understood well, data i
Re: [lwip-users] httpd: how to implement AJAX
Giuseppe Modugno wrote: > It's a pity lwip doesn't feature those >secure network layers. Actually, it's not that far away. Have a look at the for master. It's not in the releases, yet. Simon ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
Re: [lwip-users] httpd: how to implement AJAX
Il 13/11/2017 21:25, goldsi...@gmx.de ha scritto: Giuseppe Modugno wrote: The prototype for SSI callbacks is: [..] I don't see any reference to query string parameters. So how to select the right action? Sorry for the confusion. This is a mix of resource optimization, missing documentation and maybe missing framework functions. Thank you very much for your explanation. Now it is clear. My plan is to have https examples for the next release... https would be very interesting (actually a simple non-secure http server isn't really useable in public Internet). If I understood correctly, https means ssl/tls. So the first task is to add SSL/TLS to lwip, right? It's a pity lwip doesn't feature those secure network layers. ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
Re: [lwip-users] httpd: how to implement AJAX
Il 13/11/2017 18:04, Noam Weissman ha scritto: Yes SSID is a session ID that had been added to my own server code. So are you using a completely different HTTP server from the httpd that is in apps folder of lwip main source? When a user askes for a page and there is no ssid the server will redirect (send a 303) And load a login page instead. After the user writes user+password the data is sent to The server. How do you send user+password to the server? PUT? Do you encode these sensible values? The server call’s external code to check for validity of user+pass… if OK it Request a new ssid from a separate task. After that the web server sends the previously request page + ssid… every operation at the browser side must add that ssid value. Is it a cookie, right? Every time the web server gets a request with the correct ssid it clears the related timeout. If the ssid timeouts and the user asks for some data it will again redirect to the login page. Do you call a specific function from main at regular intervals to clear all SSID that expire? Regarding AJAX: How do you handle SSI ?... I am doing it differently ? I have something like this in my code: const SSI_t SSI_Table[] = { {"mem_rout", mem_routing}, {"IOSel", IO_Selection}, {"get_users", get_users}, {"ajax_reply", AjaxReply}, {NULL, NULL} // last tag must always be NULL to close the list }; mem_routing, IO_Selection, get_users, and AjaxReply are call-back function that are called by the web server as a result of encountering the proper tag… for mem_routing it is I think LWIP_HTTPD_CUSTOM_FILES is simpler to use when you have a file that is completely dynamic. Your "single tag trick" works, but IMHO is too complex for what you have to do. my AjaxReply parses the GET params and after that does something like that: How AjaxReply() function could access GET params if they aren't accessible from the SSI handler? Most probably the answer is in the file state (LWIP_HTTPD_FILE_STATE) that is filled by httpd_cgi_handler() callback (as explained by goldsimon). // get action param Char *Action = some_function(); If(strcmp(Action, “do_something_1”) == 0) { } elses If(strcmp(Action, “do_something_2”) == 0) { } else { // print a debug error : action unknown } Hope that helped, Noam. *From:*lwip-users [mailto:lwip-users-bounces+noam=silrd@nongnu.org] *On Behalf Of *Giuseppe Modugno *Sent:* Monday, November 13, 2017 6:09 PM *To:* lwip-users@nongnu.org *Subject:* Re: [lwip-users] httpd: how to implement AJAX Il 13/11/2017 14:34, Noam Weissman ha scritto: Hi, I am using the following technic for AJAX. Create an empty file named ajax.shtml or ajax.html and add it to your file list. Inside the file you only write one tag without anything else. For example Do not add CR or LF just the tag !!. Now when you issue an AJAX call the WEB server opens the file, reads it and send its data. Because the file has only the tag it will parse it, call your handler for that tag and send back To the browser just your data !! Ok, so you use SSI to create dynamic data. I tried with custom files, because *all the content* is dynamic (and not only some parts, defined by specific tags). If you use Juery it will look something like this... actually a function used as an event handler in my own code: function resetIO() { //Remove the dialog returnToPage(); $.ajax({ url: "ajax.shtml", dataType : "text", type : "GET", cache : false, data : ({ ssid: ssid, a: 'opReset', type: 2 }), error : function() { showMessage("Network Error: Sorry, there was a problem connecting to the server."); }, success : function(result) { window.location.href = document.location; } }); } In the above data you have the a: variable, this is your AJAX action !. If I understood well, data is translated in query string, in your example: GET ajax.shtml?ssid==opReset=2 Of course, is the value of ssid Javascript variable. In your own SSI/CGI code you have a table with tags + callbacks... one of the callback function Is your AJAX handler. Inside it you create an if <> else layout and handle the different actions. The prototype for SSI callbacks is: typedef u16_t (*tSSIHandler)( #if LWIP_HTTPD_SSI_RAW const char* ssi_tag_name, #else /* LWIP_HTTPD_SSI_RAW */ int iIndex, #endif /* LWIP_HTTPD_SSI_RAW */ char *pcInsert, int iInsertLen #if LWIP_HTTPD_SSI_MULTIPART , u16_t current_tag_part, u16_t *next_tag_part #
Re: [lwip-users] httpd: how to implement AJAX
Giuseppe Modugno wrote: The prototype for SSI callbacks is: [..] I don't see any reference to query string parameters. So how to select the right action? Sorry for the confusion. This is a mix of resource optimization, missing documentation and maybe missing framework functions. The idea is that we don't want to keep the http request pbuf(s) around until the end of the SSI file is transmitted (which might be long). Instead, this is done in three steps: - fs_open() calls fs_state_init(file, name) to create an object big enough to hold everything you'd need for 'file' (for custom files, you'll have to call this yourself) - httpd_cgi_handler() can parse everything needed and store it in this object - the SSI handler gets this object, too, and can access the content required (- or alternatively, in a custom read function, you might direclty access file->state) I just saw that the documentation for httpd_cgi_handler() was just cut off in the middle of a sentence. I've added a short description there. My plan is to have https examples for the next release... Simon ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
Re: [lwip-users] httpd: how to implement AJAX
Hi, Yes SSID is a session ID that had been added to my own server code. When a user askes for a page and there is no ssid the server will redirect (send a 303) And load a login page instead. After the user writes user+password the data is sent to The server. The server call's external code to check for validity of user+pass... if OK it Request a new ssid from a separate task. After that the web server sends the previously request page + ssid... every operation at the browser side must add that ssid value. Every time the web server gets a request with the correct ssid it clears the related timeout. If the ssid timeouts and the user asks for some data it will again redirect to the login page. Regarding AJAX: How do you handle SSI ?... I am doing it differently ? I have something like this in my code: const SSI_t SSI_Table[] = { {"mem_rout", mem_routing}, {"IOSel", IO_Selection}, {"get_users", get_users}, {"ajax_reply", AjaxReply}, {NULL, NULL} // last tag must always be NULL to close the list }; mem_routing, IO_Selection, get_users, and AjaxReply are call-back function that are called by the web server as a result of encountering the proper tag... for mem_routing it is my AjaxReply parses the GET params and after that does something like that: // get action param Char *Action = some_function(); If(strcmp(Action, "do_something_1") == 0) { } elses If(strcmp(Action, "do_something_2") == 0) { } else { // print a debug error : action unknown } Hope that helped, Noam. From: lwip-users [mailto:lwip-users-bounces+noam=silrd@nongnu.org] On Behalf Of Giuseppe Modugno Sent: Monday, November 13, 2017 6:09 PM To: lwip-users@nongnu.org Subject: Re: [lwip-users] httpd: how to implement AJAX Il 13/11/2017 14:34, Noam Weissman ha scritto: Hi, I am using the following technic for AJAX. Create an empty file named ajax.shtml or ajax.html and add it to your file list. Inside the file you only write one tag without anything else. For example Do not add CR or LF just the tag !!. Now when you issue an AJAX call the WEB server opens the file, reads it and send its data. Because the file has only the tag it will parse it, call your handler for that tag and send back To the browser just your data !! Ok, so you use SSI to create dynamic data. I tried with custom files, because *all the content* is dynamic (and not only some parts, defined by specific tags). If you use Juery it will look something like this... actually a function used as an event handler in my own code: function resetIO() { //Remove the dialog returnToPage(); $.ajax({ url: "ajax.shtml", dataType : "text", type : "GET", cache : false, data : ({ ssid: ssid, a: 'opReset', type: 2 }), error : function() { showMessage("Network Error: Sorry, there was a problem connecting to the server."); }, success : function(result) { window.location.href = document.location; } }); } In the above data you have the a: variable, this is your AJAX action !. If I understood well, data is translated in query string, in your example: GET ajax.shtml?ssid==opReset=2 Of course, is the value of ssid Javascript variable. In your own SSI/CGI code you have a table with tags + callbacks... one of the callback function Is your AJAX handler. Inside it you create an if <> else layout and handle the different actions. The prototype for SSI callbacks is: typedef u16_t (*tSSIHandler)( #if LWIP_HTTPD_SSI_RAW const char* ssi_tag_name, #else /* LWIP_HTTPD_SSI_RAW */ int iIndex, #endif /* LWIP_HTTPD_SSI_RAW */ char *pcInsert, int iInsertLen #if LWIP_HTTPD_SSI_MULTIPART , u16_t current_tag_part, u16_t *next_tag_part #endif /* LWIP_HTTPD_SSI_MULTIPART */ #if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE , void *connection_state #endif /* LWIP_HTTPD_FILE_STATE */ ); I don't see any reference to query string parameters. So how to select the right action? The HTTP server will read your ajax.shtml file and because it has nothing BUT your tag it will only send back the dynamic data you process in your ajax handling function. As said before, it works if the dynamic content depends only from the name of the file (ajax.shtml in your example) and not from the action in the query string (a=opReset). Where is my error? Another question. I saw ssid in your javascript example. Is it related to a "session identifier"? If so, did you implement a sessi
Re: [lwip-users] httpd: how to implement AJAX
Noam Weissman wrote: >Create an empty file named ajax.shtml or ajax.html and add it to your >file list. > >Inside the file you only write one tag without anything else. For >example That's a nice idea. I also have task #14269 open to make ssi processing independent of the file's extension (a makefsdata change). Simon ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
Re: [lwip-users] httpd: how to implement AJAX
Il 13/11/2017 14:34, Noam Weissman ha scritto: Hi, I am using the following technic for AJAX. Create an empty file named ajax.shtml or ajax.html and add it to your file list. Inside the file you only write one tag without anything else. For example Do not add CR or LF just the tag !!. Now when you issue an AJAX call the WEB server opens the file, reads it and send its data. Because the file has only the tag it will parse it, call your handler for that tag and send back To the browser just your data !! Ok, so you use SSI to create dynamic data. I tried with custom files, because *all the content* is dynamic (and not only some parts, defined by specific tags). If you use Juery it will look something like this... actually a function used as an event handler in my own code: function resetIO() { //Remove the dialog returnToPage(); $.ajax({ url: "ajax.shtml", dataType : "text", type : "GET", cache : false, data : ({ ssid: ssid, a: 'opReset', type: 2 }), error : function() { showMessage("Network Error: Sorry, there was a problem connecting to the server."); }, success : function(result) { window.location.href = document.location; } }); } In the above data you have the a: variable, this is your AJAX action !. If I understood well, data is translated in query string, in your example: GET ajax.shtml?ssid==opReset=2 Of course, is the value of ssid Javascript variable. In your own SSI/CGI code you have a table with tags + callbacks... one of the callback function Is your AJAX handler. Inside it you create an if <> else layout and handle the different actions. The prototype for SSI callbacks is: typedef u16_t (*tSSIHandler)( #if LWIP_HTTPD_SSI_RAW const char* ssi_tag_name, #else /* LWIP_HTTPD_SSI_RAW */ int iIndex, #endif /* LWIP_HTTPD_SSI_RAW */ char *pcInsert, int iInsertLen #if LWIP_HTTPD_SSI_MULTIPART , u16_t current_tag_part, u16_t *next_tag_part #endif /* LWIP_HTTPD_SSI_MULTIPART */ #if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE , void *connection_state #endif /* LWIP_HTTPD_FILE_STATE */ ); I don't see any reference to query string parameters. So how to select the right action? The HTTP server will read your ajax.shtml file and because it has nothing BUT your tag it will only send back the dynamic data you process in your ajax handling function. As said before, it works if the dynamic content depends only from the name of the file (ajax.shtml in your example) and not from the action in the query string (a=opReset). Where is my error? Another question. I saw ssid in your javascript example. Is it related to a "session identifier"? If so, did you implement a session mechanism over httpd? ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
Re: [lwip-users] httpd: how to implement AJAX
Hi, I am using the following technic for AJAX. Create an empty file named ajax.shtml or ajax.html and add it to your file list. Inside the file you only write one tag without anything else. For example Do not add CR or LF just the tag !!. Now when you issue an AJAX call the WEB server opens the file, reads it and send its data. Because the file has only the tag it will parse it, call your handler for that tag and send back To the browser just your data !! If you use Juery it will look something like this... actually a function used as an event handler in my own code: function resetIO() { //Remove the dialog returnToPage(); $.ajax({ url: "ajax.shtml", dataType : "text", type : "GET", cache : false, data : ({ ssid: ssid, a: 'opReset', type: 2 }), error : function() { showMessage("Network Error: Sorry, there was a problem connecting to the server."); }, success : function(result) { window.location.href = document.location; } }); } In the above data you have the a: variable, this is your AJAX action !. In your own SSI/CGI code you have a table with tags + callbacks... one of the callback function Is your AJAX handler. Inside it you create an if <> else layout and handle the different actions. The HTTP server will read your ajax.shtml file and because it has nothing BUT your tag it will only send back the dynamic data you process in your ajax handling function. Hope that helped, Noam. -Original Message- From: lwip-users [mailto:lwip-users-bounces+noam=silrd@nongnu.org] On Behalf Of Giuseppe Modugno Sent: Monday, November 13, 2017 12:43 PM To: lwip-users@nongnu.org Subject: [lwip-users] httpd: how to implement AJAX I'm trying to create a website with AJAX technology: the client polls, at regular intervals, the server with GET requests of file /status.json. The response is dynamic. I could use only LWIP_HTTPD_CUSTOM_FILES and create the file at runtime in fs_open_custom(). It works, but I can't decode the query string, because it isn't passed to fs_open_custom() callback. So I thought to use LWIP_HTTPD_CGI_SSI instead of LWIP_HTTPD_CUSTOM_FILES, but I have some difficulties to understand how it works. First of all, the file /status.json must be present in the filesystem (fs_open() must return ERR_OK), otherwise httpd_cgi_handler() isn't called at all. However I can't return any data in httpd_cgi_handler(). Any help? ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users
[lwip-users] httpd: how to implement AJAX
I'm trying to create a website with AJAX technology: the client polls, at regular intervals, the server with GET requests of file /status.json. The response is dynamic. I could use only LWIP_HTTPD_CUSTOM_FILES and create the file at runtime in fs_open_custom(). It works, but I can't decode the query string, because it isn't passed to fs_open_custom() callback. So I thought to use LWIP_HTTPD_CGI_SSI instead of LWIP_HTTPD_CUSTOM_FILES, but I have some difficulties to understand how it works. First of all, the file /status.json must be present in the filesystem (fs_open() must return ERR_OK), otherwise httpd_cgi_handler() isn't called at all. However I can't return any data in httpd_cgi_handler(). Any help? ___ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users