Processing POST using Forms

Posted on
  • Processing POST using Forms
    This link shows how a Form is setup in HTML using both the GET and POST methods.
    http://www.w3schools.com/tags/att_form_m­ethod.asp
    The first line action refers to an ASP file on the server. The Posted data is processed by the ASP code.

    form action="demo_form_method_post.asp" method="post">
    

    For Espruino perhaps we can replace the ASP with a word that is used to steer the message to an appropriate handler.
    One idea would be to use a Form to setup the column titles in a CSV file. It would create a CSV file on the SD card, taking the filename and column headers from the posted form. Ideas?
    In previous forum posts we did the JSON POST from Java Script.
    http://forum.espruino.com/conversations/­285131/
    Set up an HTML file called Postform2.html and copy it to the SD card

    I tried to list it here but it doesn't work in the preview. So I attached it.

    Part of the server code with console.log(“Header “,req.headers) added.

    var pdata="";
    function serveHTML(){
    var http=require("http").createServer(onPage­Request).listen(8080);
    }//end serveFile
    
    function onPageRequest(req, res) { 
    //console.log("Req= ",req);
    console.log("Header",req.headers);
      var a = url.parse(req.url, true);
    console.log("URL ",a);
    if (req.method=="POST") {
      console.log("Post");
      doPost(req,res);
    }else{
      doGet(req,res);
    }//endif
    }//end on PageRequest
    

    The header and results of url.parse when Postform2.html is loaded and the Submit button is pressed.

    Header {
      "Accept": "text/html, application/xhtml+xml, */*",
      "Referer": "http://192.168.1.3:8080/PostForm2.html"­,
      "Accept-Language": "en-US",
      "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
      "Content-Type": "application/x-www-form-urlencoded",
      "Accept-Encoding": "gzip, deflate",
      "Host": "192.168.1.3:8080",
      "Content-Length": "19",
      "DNT": "1",
      "Connection": "Keep-Alive",
      "Cache-Control": "no-cache"
     }
    URL  {
      "method": "GET",
      "host": "",
      "path": "/LOGdata",
      "pathname": "/LOGdata",
      "search": null, "port": null, "query": null }
    Post
    Length  19
    pdata=  fname=xxx&lname=yyy
    pdata length=  19
    

    It’s strange to see GET in the URL results. Suggestions?
    The pdata is the message received after the header.
    It would be prudent to add code to limit the number of characters we can receive so that memory isn’t exhausted. The server code as of now crashes when the Submit button is pressed.

    Repeating with the JPpost9.HTML using the JSON post from a script. The LED1 button was clicked.
    The header and results of url.parse

    Header {
      "Accept": "*/*",
      "Content-Type": "application/json;charset=utf8",
      "Referer": "http://192.168.1.3:8080/JPpostT9.html",­
      "Accept-Language": "en-US",
      "Accept-Encoding": "gzip, deflate",
      "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
      "Host": "192.168.1.3:8080",
      "Content-Length": "70",
      "DNT": "1",
      "Connection": "Keep-Alive",
      "Cache-Control": "no-cache"
     }
    URL  {
      "method": "GET",
      "host": "",
      "path": "/CMD",
      "pathname": "/CMD",
      "search": null, "port": null, "query": null }
    Post
    Length  70
    pdata=  {"name":"LED1","a":0,"cmd":"pobj.a=!pobj­.a;digitalWrite(LED1,pobj.a)"}
    pdata length=  70
    {
      "name": "LED1",
      "a": 0,
      "cmd": "pobj.a=!pobj.a;digitalWrite(LED1,pobj.a­)"
     }
    Closed
    >
    

    So the code needs to use req.method to determine GET or POST.
    If it’s a POST, then use
    var a = url.parse(req.url, true);
    and a.”path”, or a.”pathname” to determine if it’s a “CMD” or a “LOGdata” POST.
    Anyone have a guess which is the right one?
    If it’s not what’s coded in the server, the reply header should be 404?

    One issue is that when the Submit button is pressed a new tab in the browser is opened.
    This is resolved by changing the target attribute in the HTML file.
    http://www.w3schools.com/tags/att_form_t­arget.asp
    form action="LOGdata" method="post" target="_blank">

    More to follow.


    1 Attachment

  • The missing files are attached.


    2 Attachments

  • Limiting the length of POST data to prevent filling memory?

    A POST from a client sends a header and a block of data. If a client sends too much data at once the server will run out of space and crash. I added code to ignore POST data over a certain size.
    Is this sufficient or should an req.on('data) be used to drain the buffer at the req source?

    function serveHTML(){
    var http=require("http").createServer(onPage­Request).listen(8080);
    }//end serveFile
    
    var pdata="";
    function onPageRequest(req, res) { 
    //console.log("Req= ",req);
    //console.log("Header",req.headers);
    if (req.method=="POST") {
      console.log("Post");
      doPost(req,res);
    }else{
      doGet(req,res);
    }//endif
    }//end on PageRequest
    
    var pobj;
    
    
    function doPost(req,res){
    var length;
      length=req.headers["Content-Length"];
    //do we want to take the message based on length?
      if(length<1024){
      req.on("data", function(d) {pdata+=d;if(pdata.length==length)doPost­1(req,res);});
      }else{
    /*********
    Should an req.on('data') be used here to drain the source and toss the data?
    */
    
      res.writeHead(413); //Too big error
      res.end();  }//end if length    
      req.on('close',"console.log(\"Closed\",p­data);");
    }
    

    The POST message processing code follows.

    function doPost1(req,res){
    var length;
    var a = url.parse(req.url, true);
    console.log("URL ",a);
    console.log("XXX ",a.pathname);
      length=req.headers["Content-Length"];
      console.log("Length ",length);
      console.log("pdata= ",pdata);
      console.log("pdata length= ",pdata.length);
      switch (a.pathname){
        case "/CMD":                                //Process JSON command structure
         if(pdata.length==length){
          pobj=JSON.parse(pdata);
          console.log(pobj);
          if(pobj.cmd !==null){
           eval(pobj.cmd);
           pdata=JSON.stringify(pobj);
           res.writeHead(200);
           res.end(pdata);
          }else{
           res.writeHead(201);
           res.end();
          }  //end if pobj.cmd
         }//endif length else
        break;
        case "/LOGdata":    // Process data POSTed into a form, simple Echo for now
         console.log("LOGdata= ",pdata);
         res.writeHead(200);
         res.end(pdata);
        break;
        default:
         res.writeHead(404);
         res.end();
     }//end switch
     pdata="";
    }//end doPost1
    
    
  • I'd do:

    req.on("data", function(d) {
      if (pdata.length>1024) return;
      pdata+=d;
      ...
    

    If you're in control of everything, hopefully nothing will ever overflow - but if you're trying to protect against someone deliberately sending more data then they could very easily fake the Content-Length header.

  • For anyone else who gets here, there's now a tutorial on HTTP POST and Forms: http://www.espruino.com/Posting+Forms

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Processing POST using Forms

Posted by Avatar for ClearMemory041063 @ClearMemory041063

Actions