newLISP Fan Club

Forum => newLISP and the O.S. => Topic started by: Kirill on January 13, 2011, 04:43:13 AM

Title: HTTP POST processing
Post by: Kirill on January 13, 2011, 04:43:13 AM
Hi there,



cgi.lsp (//http) processes POST parameters using read-line:



; get stdin POST method parameters if present
;
(set 'inline (read-line))
(if inline
(set 'params (get-vars inline)))
 
(if (not params) (set 'params '()))


Today I tried this when CGI ran under Mathopd (//http) and it did not work (or actually I was using web.lsp (//http), but the issue is similar with cgi.lsp): when some data was sent using POST, the script was simply hanging waiting for something. CGI environment provides the length of POST-ed data en CONTENT_LENGTH. So, a (read) should rather be used to collect POST-ed data. For web.lsp, I have a patch (//http). For cgi.lsp, the code might look like this (replacing the code above):



; get stdin POST method parameters if present
;
(when (= (env "HTTP_METHOD") "POST")
  (read (device) post-data (integer (env "CONTENT_LENGTH")))
  (set 'params (get-vars post-data)))

(if (not params) (set 'params '()))


I have not actually tried it, as I'm not using cgi.lsp, but it seems correct.



Thanks.



EDIT: After I submitted the post, I went through the nl-web.c and it seems to me that my changes will not work with newLISP's built in web server's CGI handler, as it does not set the CONTENT_LENGTH variable. Actually it only sets a subset of variables, at least compared to what CGI/1.1 spec says. It might be worth mentioning in the docs that CGI environment variables apart from the mentioned HTTP_HOST, HTTP_USER_AGENT and HTTP_COOKIE (and some other) are not being set.
Title: Re: HTTP POST processing
Post by: Lutz on January 27, 2011, 03:54:21 PM
In version 10.3.0, to be released in February, newLISP HTTP server will also set the CONTENT_LENGTH environment variable when present in the incoming client request.



You can see a preview of 10.3.0 here:



http://www.newlisp.org/downloads/development/inprogress/
Title: Re: HTTP POST processing
Post by: Kirill on January 27, 2011, 11:59:55 PM
Rather than trusting client's headers, would not it be better to let newLISP calculate contect length itself? It's just I don't want to let the client decide how much data I'll need to read().



How about other CGI environment variables, Lutz? In particular, I'm thinking of HTTP_AUTHORIZATION, which becomes set if the client does HTTP AUTH. Doing so, it should be easy to write password-protected somethings using newLISP's built-in web server. Like this:



(define (www-not-auth)
  (println "Status: 401 Authorization required")
  (println "WWW-Authenticate: Basic realm="Protected"")
  (println "Content-type: text/plain")
  (println "")
  (println "Please provide a valid username and password")
  (exit))

(unless (and (env "HTTP_AUTHORIZATION")
             (starts-with (env "HTTP_AUTHORIZATION") "basic " 1))
  (www-not-auth))

(setq login-data (parse (base64-dec ((parse (env "HTTP_AUTHORIZATION")) 1)) ":"))

; verify username available as (login-data 0) and password available as (login-data 1)
; and call (www-not-auth) if authentication fails

(env "REMOTE_USER" (login-data 0))
(env "HTTP_AUTHORIZATION" "")


I (load) this in CGI scripts which deal with several users.
Title: Re: HTTP POST processing
Post by: Kirill on January 28, 2011, 12:53:46 AM
Lutz - will you also update cgi.lsp accordingly, so it uses CONTENT_LENGTH correctly?
Title: Re: HTTP POST processing
Post by: Lutz on January 28, 2011, 04:40:08 AM
Yes, but not yet. cgi.lsp will be updated eventually, but I will wait a few versions, so new code will still run on older versions of newLISP server.
Title: Re: HTTP POST processing
Post by: Kirill on January 29, 2011, 12:00:56 PM
cgi.lsp can check for the presence of CONTENT_LENGTH, no?
Title: Re: HTTP POST processing
Post by: Lutz on January 30, 2011, 04:55:21 AM
Yes, that is what it's doing now in the preview:



http://www.newlisp.org/downloads/development/inprogress/



ps: final 10.3.0 has been released February 2nd