On Sat, 8 Apr 2006, DaishiKato wrote:
At Fri, 7 Apr 2006 17:27:43 +0000 (GMT),
Thomas Chust wrote:
This works on my machine and looks fine as far as the use of the openssl
egg is concerned. I would like to remark, though, that it may be useful if
one could somehow specify the second optional parameter to ssl-connect to
enable SSL protocol version selection and certificate management -- maybe
one could hack an additional field into the http:request structure.
You are absolutely right.
In fact, I was wondering how to specify CA certificates.
Here is a new patch.
Great, looks good and works fine.
I think it should be possible to just create a version of http:GET with
three optional arguments, [...]
This is still different from what I desire.
I was thinking something like a global pool of connections
for each host:port, and a client program does not need to
keep track of input and output ports.
It can even seamlessly re-connect, once the old connection is closed.
[...]
I have previously implemented this type of connection management in the
rpc egg, so I threw together some code from there and from http-client to
create an interface that seems to work fine. The source code is attached
to this e-mail.
cu,
Thomas
;;;; persistent-http-get.scm
;;;; A replacement for http:GET that uses a pool of persistent connections
(define-extension persistent-http-get
(export
persistent-http:is-connected? persistent-http:get-connection
persistent-http:close-connection! persistent-http:close-all-connections!
persistent-http:GET))
(require-extension (srfi 18) (srfi 69) extras url http-utils http-client)
;;; Network support routines
#>
#ifdef _WIN32
#if _MSC_VER > 1300
#include <winsock2.h>
#else /* _MSC_VER */
#include <winsock.h>
#endif /* _MSC_VER */
#else /* _WIN32 */
#include <netinet/in.h>
#include <netdb.h>
#endif /* _WIN32 */
<#
(define (get-port-by-service-name svc)
(let ((port ((foreign-lambda* scheme-object ((c-string svc))
"struct servent *sve =\n"
" getservbyname(svc, \"tcp\");\n"
"return(sve == NULL\n"
" ? C_SCHEME_FALSE\n"
" : C_fix(ntohs(sve->s_port)));\n")
svc)))
(if port
port
(error 'get-port-by-service-name "unknown service" svc))))
;;; Thread local connection pool
(define connections
(make-parameter (make-hash-table equal?)))
(define connections-owner
(make-parameter (current-thread)))
(define (ensure-local-connections)
(unless (eq? (connections-owner) (current-thread))
(connections (make-hash-table equal?))
(connections-owner (current-thread))))
(define (request-server-id req)
(let* ((req (if (string? req)
(http:make-request 'GET req)
req))
(u (url (http:request-url req)))
(scheme (or (url-scheme u) "http"))
(host (or (http:request-ip req) (url-host u)))
(port (or (url-port u) (get-port-by-service-name scheme))))
(sprintf "~A://[EMAIL PROTECTED]:~A" scheme (url-user u) host port)))
(define (persistent-http:is-connected? req)
(ensure-local-connections)
(hash-table-exists? (connections) (request-server-id req)))
(define (persistent-http:get-connection req)
(ensure-local-connections)
(apply values (hash-table-ref (connections) (request-server-id req))))
(define (persistent-http:close-connection! req)
(ensure-local-connections)
(let ((key (request-server-id req)))
(let ((con (hash-table-ref (connections) key)))
(hash-table-delete! (connections) key)
(close-input-port (car con))
(close-output-port (cadr con)))))
(define (persistent-http:close-all-connections!)
(ensure-local-connections)
(hash-table-walk
(connections)
(lambda (key con)
(hash-table-delete! (connections) key)
(close-input-port (car con))
(close-output-port (cadr con)))))
;;; HTTP client functionality
(define (persistent-http:GET req #!optional (keep-alive? #t))
(ensure-local-connections)
(let* ((req (if (string? req)
(http:make-request
'GET req
`(("Connection" . ,(if keep-alive?
"keep-alive"
"close"))))
req))
(key (request-server-id req))
(stat #f)
(hdrs '())
(in #f)
(out #f))
(dynamic-wind
void
(lambda ()
(set!-values
(in out)
(apply values (hash-table-ref/default (connections) key '(#f #f))))
(let retry ()
(condition-case
(set!-values
(stat hdrs in out)
(http:send-request req in out))
(exn (exn i/o net)
(if (and in out)
(begin
(close-input-port in)
(close-output-port out)
(hash-table-delete! (connections) key)
(set! in #f)
(set! out #f)
(retry))
(signal exn)))))
(if (eof-object? stat)
#!eof
(read-string
(cond
((alist-ref "content-length" hdrs equal?)
=> string->number)
(else
#f))
in)))
(lambda ()
(if (and keep-alive?
(not (string-ci=?
(alist-ref "connection" hdrs equal? "")
"close")))
(hash-table-set! (connections) key (list in out))
(begin
(close-input-port in)
(close-output-port out)
(hash-table-delete! (connections) key)))))))
;;;; vim:set shiftwidth=2 softtabstop=2: ;;;;
_______________________________________________
Chicken-users mailing list
Chicken-users@nongnu.org
http://lists.nongnu.org/mailman/listinfo/chicken-users