mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-09 21:40:33 +02:00
web: Add 'current-https-proxy' and honor $https_proxy.
* module/web/client.scm (current-https-proxy): New variable. (setup-http-tunnel): New procedure. (open-socket-for-uri): Move 'http-proxy', 'uri', and 'addresses' inside 'open-socket'. Remove 'with-https-proxy' macro. Add call to 'setup-http-tunnel'. Honor 'current-https-proxy' in 'open-socket'. * doc/ref/web.texi (Web Client): Document 'current-https-proxy'. * doc/ref/guile.texi: Update copyright years. Based on Guix commit 9bc8175cfa6b23c31f6c43531377d266456e430e. Co-authored-by: Sou Bunnbu (宋文武) <iyzsong@gmail.com>
This commit is contained in:
parent
c9b83a27c7
commit
80bbebef4d
2 changed files with 53 additions and 39 deletions
|
@ -1,6 +1,6 @@
|
||||||
@c -*-texinfo-*-
|
@c -*-texinfo-*-
|
||||||
@c This is part of the GNU Guile Reference Manual.
|
@c This is part of the GNU Guile Reference Manual.
|
||||||
@c Copyright (C) 2010, 2011, 2012, 2013, 2015, 2018, 2019 Free Software Foundation, Inc.
|
@c Copyright (C) 2010, 2011, 2012, 2013, 2015, 2018, 2019, 2020 Free Software Foundation, Inc.
|
||||||
@c See the file guile.texi for copying conditions.
|
@c See the file guile.texi for copying conditions.
|
||||||
|
|
||||||
@node Web
|
@node Web
|
||||||
|
@ -1540,10 +1540,11 @@ Another option, good but not as performant, would be to use threads,
|
||||||
possibly via par-map or futures.
|
possibly via par-map or futures.
|
||||||
|
|
||||||
@deffn {Scheme Parameter} current-http-proxy
|
@deffn {Scheme Parameter} current-http-proxy
|
||||||
|
@deffnx {Scheme Parameter} current-https-proxy
|
||||||
Either @code{#f} or a non-empty string containing the URL of the HTTP
|
Either @code{#f} or a non-empty string containing the URL of the HTTP
|
||||||
proxy server to be used by the procedures in the @code{(web client)}
|
or HTTPS proxy server to be used by the procedures in the @code{(web client)}
|
||||||
module, including @code{open-socket-for-uri}. Its initial value is
|
module, including @code{open-socket-for-uri}. Its initial value is
|
||||||
based on the @env{http_proxy} environment variable.
|
based on the @env{http_proxy} and @env{https_proxy} environment variables.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
(current-http-proxy) @result{} "http://localhost:8123/"
|
(current-http-proxy) @result{} "http://localhost:8123/"
|
||||||
|
|
|
@ -45,7 +45,9 @@
|
||||||
#:use-module (srfi srfi-9 gnu)
|
#:use-module (srfi srfi-9 gnu)
|
||||||
#:use-module ((rnrs io ports)
|
#:use-module ((rnrs io ports)
|
||||||
#:prefix rnrs-ports:)
|
#:prefix rnrs-ports:)
|
||||||
|
#:use-module (ice-9 match)
|
||||||
#:export (current-http-proxy
|
#:export (current-http-proxy
|
||||||
|
current-https-proxy
|
||||||
open-socket-for-uri
|
open-socket-for-uri
|
||||||
http-request
|
http-request
|
||||||
http-get
|
http-get
|
||||||
|
@ -83,6 +85,11 @@ if it is unavailable."
|
||||||
(and (not (equal? proxy ""))
|
(and (not (equal? proxy ""))
|
||||||
proxy))))
|
proxy))))
|
||||||
|
|
||||||
|
(define current-https-proxy
|
||||||
|
(make-parameter (let ((proxy (getenv "https_proxy")))
|
||||||
|
(and (not (equal? proxy ""))
|
||||||
|
proxy))))
|
||||||
|
|
||||||
(define (tls-wrap port server)
|
(define (tls-wrap port server)
|
||||||
"Return PORT wrapped in a TLS connection to SERVER. SERVER must be a DNS
|
"Return PORT wrapped in a TLS connection to SERVER. SERVER must be a DNS
|
||||||
host name without trailing dot."
|
host name without trailing dot."
|
||||||
|
@ -159,9 +166,30 @@ host name without trailing dot."
|
||||||
((uri-reference? uri-or-string) uri-or-string)
|
((uri-reference? uri-or-string) uri-or-string)
|
||||||
(else (error "Invalid URI-reference" uri-or-string))))
|
(else (error "Invalid URI-reference" uri-or-string))))
|
||||||
|
|
||||||
|
(define (setup-http-tunnel port uri)
|
||||||
|
"Establish over PORT an HTTP tunnel to the destination server of URI."
|
||||||
|
(define target
|
||||||
|
(string-append (uri-host uri) ":"
|
||||||
|
(number->string
|
||||||
|
(or (uri-port uri)
|
||||||
|
(match (uri-scheme uri)
|
||||||
|
('http 80)
|
||||||
|
('https 443))))))
|
||||||
|
(format port "CONNECT ~a HTTP/1.1\r\n" target)
|
||||||
|
(format port "Host: ~a\r\n\r\n" target)
|
||||||
|
(force-output port)
|
||||||
|
(read-response port))
|
||||||
|
|
||||||
(define (open-socket-for-uri uri-or-string)
|
(define (open-socket-for-uri uri-or-string)
|
||||||
"Return an open input/output port for a connection to URI."
|
"Return an open input/output port for a connection to URI."
|
||||||
(define http-proxy (current-http-proxy))
|
(define uri
|
||||||
|
(ensure-uri-reference uri-or-string))
|
||||||
|
(define https?
|
||||||
|
(eq? 'https (uri-scheme uri)))
|
||||||
|
|
||||||
|
(define (open-socket)
|
||||||
|
(define http-proxy
|
||||||
|
(if https? (current-https-proxy) (current-http-proxy)))
|
||||||
(define uri (ensure-uri-reference (or http-proxy uri-or-string)))
|
(define uri (ensure-uri-reference (or http-proxy uri-or-string)))
|
||||||
(define addresses
|
(define addresses
|
||||||
(let ((port (uri-port uri)))
|
(let ((port (uri-port uri)))
|
||||||
|
@ -175,9 +203,7 @@ host name without trailing dot."
|
||||||
0))
|
0))
|
||||||
(lambda (ai1 ai2)
|
(lambda (ai1 ai2)
|
||||||
(equal? (addrinfo:addr ai1) (addrinfo:addr ai2))))))
|
(equal? (addrinfo:addr ai1) (addrinfo:addr ai2))))))
|
||||||
(define https?
|
|
||||||
(eq? 'https (uri-scheme uri)))
|
|
||||||
(define (open-socket)
|
|
||||||
(let loop ((addresses addresses))
|
(let loop ((addresses addresses))
|
||||||
(let* ((ai (car addresses))
|
(let* ((ai (car addresses))
|
||||||
(s (with-fluids ((%default-port-encoding #f))
|
(s (with-fluids ((%default-port-encoding #f))
|
||||||
|
@ -199,29 +225,16 @@ host name without trailing dot."
|
||||||
(apply throw args)
|
(apply throw args)
|
||||||
(loop (cdr addresses))))))))
|
(loop (cdr addresses))))))))
|
||||||
|
|
||||||
(let-syntax ((with-https-proxy
|
|
||||||
(syntax-rules ()
|
|
||||||
((_ exp)
|
|
||||||
;; For HTTPS URIs, honor 'https_proxy', not 'http_proxy'.
|
|
||||||
;; FIXME: Proxying is not supported for https.
|
|
||||||
(let ((thunk (lambda () exp)))
|
|
||||||
(if (and https?
|
|
||||||
current-http-proxy)
|
|
||||||
(parameterize ((current-http-proxy #f))
|
|
||||||
(when (and=> (getenv "https_proxy")
|
|
||||||
(negate string-null?))
|
|
||||||
(format (current-error-port)
|
|
||||||
"warning: 'https_proxy' is ignored~%"))
|
|
||||||
(thunk))
|
|
||||||
(thunk)))))))
|
|
||||||
(with-https-proxy
|
|
||||||
(let ((s (open-socket)))
|
(let ((s (open-socket)))
|
||||||
;; Buffer input and output on this port.
|
;; Buffer input and output on this port.
|
||||||
(setvbuf s 'block %http-receive-buffer-size)
|
(setvbuf s 'block %http-receive-buffer-size)
|
||||||
|
|
||||||
|
(when (and https? (current-https-proxy))
|
||||||
|
(setup-http-tunnel s uri))
|
||||||
|
|
||||||
(if https?
|
(if https?
|
||||||
(tls-wrap s (uri-host uri))
|
(tls-wrap s (uri-host uri))
|
||||||
s)))))
|
s)))
|
||||||
|
|
||||||
(define (extend-request r k v . additional)
|
(define (extend-request r k v . additional)
|
||||||
(let ((r (set-field r (request-headers)
|
(let ((r (set-field r (request-headers)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue