;;;; web-client.test --- HTTP client -*- mode: scheme; coding: utf-8; -*- ;;;; ;;;; Copyright (C) 2013 Free Software Foundation, Inc. ;;;; ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public ;;;; License as published by the Free Software Foundation; either ;;;; version 3 of the License, or (at your option) any later version. ;;;; ;;;; This library is distributed in the hope that it will be useful, ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;;; Lesser General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU Lesser General Public ;;;; License along with this library; if not, write to the Free Software ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA (define-module (test-suite web-client) #:use-module (web client) #:use-module (web request) #:use-module (web response) #:use-module (ice-9 iconv) #:use-module (ice-9 binary-ports) #:use-module (test-suite lib)) (define get-request-headers:www.gnu.org/software/guile/ "GET /software/guile/ HTTP/1.1 Host: www.gnu.org Connection: close ") (define get-response-headers:www.gnu.org/software/guile/ "HTTP/1.1 200 OK Date: Fri, 11 Jan 2013 10:59:11 GMT Server: Apache/2.2.14 Accept-Ranges: bytes Cache-Control: max-age=0 Expires: Fri, 11 Jan 2013 10:59:11 GMT Vary: Accept-Encoding Content-Length: 8077 Connection: close Content-Type: text/html Content-Language: en ") (define get-response-body:www.gnu.org/software/guile/ " GNU Guile (About Guile)
\t \t \"Guile\" \t \t

The GNU extension language

\t

About Guile


\t \t \t \t \t \t \t \t \t \t
\t

About Guile
\t\tWhat is Guile?
\t\tNews
\t\tCommunity
\t

\t \t

Documentation
\t\tManuals
\t\tFAQ's
\t

\t

Download
\t\tReleases
\t\tRepository
\t\tSnapshots
\t

\t

Projects
\t\tCore
\t\tGUI
\t\tFile Formats
\t\tNetworking
\t\tTools
\t\tApplications
\t

\t \t

Development
\t\tProject summary
\t\tHelping out
\t\tCool ideas
\t

\t

Resources
\t\tGuile Resources
\t\tScheme Resources
\t

\t

GNU Project home page

What is Guile?

Getting Guile

\t

What is Guile? What can it do for you?

Guile is the GNU Ubiquitous Intelligent Language for Extensions, the official extension language for the GNU operating system.

Guile is a library designed to help programmers create flexible applications. Using Guile in an application allows the application's functionality to be extended by users or other programmers with plug-ins, modules, or scripts. Guile provides what might be described as \"practical software freedom,\" making it possible for users to customize an application to meet their needs without digging into the application's internals.

There is a long list of proven applications that employ extension languages. Successful and long-lived examples of Free Software projects that use Guile are TeXmacs, LilyPond, and GnuCash.

Guile is a programming language

Guile is an interpreter and compiler for the Scheme programming language, a clean and elegant dialect of Lisp. Guile is up to date with recent Scheme standards, supporting the Revised5 and most of the Revised6 language reports (including hygienic macros), as well as many SRFIs. It also comes with a library of modules that offer additional features, like an HTTP server and client, XML parsing, and object-oriented programming.

Guile is an extension language platform

Guile is an efficient virtual machine that executes a portable instruction set generated by its optimizing compiler, and integrates very easily with C and C++ application code. In addition to Scheme, Guile includes compiler front-ends for ECMAScript and Emacs Lisp (support for Lua is underway), which means your application can be extended in the language (or languages) most appropriate for your user base. And Guile's tools for parsing and compiling are exposed as part of its standard module set, so support for additional languages can be added without writing a single line of C.

Guile gives your programs more power

Using Guile with your program makes it more usable. Users don't need to learn the plumbing of your application to customize it; they just need to understand Guile, and the access you've provided. They can easily trade and share features by downloading and creating scripts, instead of trading complex patches and recompiling their applications. They don't need to coordinate with you or anyone else. Using Guile, your application has a full-featured scripting language right from the beginning, so you can focus on the novel and attention-getting parts of your application.

How do I get Guile?

  • The current stable release is 2.0.7.

See the Download page for additional ways of getting Guile.


Please send FSF & GNU inquiries & questions to gnu@gnu.org. There are also other ways to contact the FSF.

Please send comments on these web pages to bug-guile@gnu.org, send other questions to gnu@gnu.org.

Copyright (C) 2012 Free Software Foundation, Inc.

Verbatim copying and distribution of this entire web page is permitted in any medium, provided this notice is preserved.

Updated: $Date: 2012/11/30 00:16:15 $ $Author: civodul $

") (define head-request-headers:www.gnu.org/software/guile/ "HEAD /software/guile/ HTTP/1.1 Host: www.gnu.org Connection: close ") (define head-response-headers:www.gnu.org/software/guile/ "HTTP/1.1 200 OK Date: Fri, 11 Jan 2013 11:03:14 GMT Server: Apache/2.2.14 Accept-Ranges: bytes Cache-Control: max-age=0 Expires: Fri, 11 Jan 2013 11:03:14 GMT Vary: Accept-Encoding Content-Length: 8077 Connection: close Content-Type: text/html Content-Language: en ") ;; Unfortunately, POST to http://www.gnu.org/software/guile/ succeeds! (define post-request-headers:www.apache.org/ "POST / HTTP/1.1 Host: www.apache.org Connection: close ") (define post-response-headers:www.apache.org/ "HTTP/1.1 405 Method Not Allowed Date: Fri, 11 Jan 2013 11:04:34 GMT Server: Apache/2.4.3 (Unix) OpenSSL/1.0.0g Allow: TRACE Content-Length: 314 Connection: close Content-Type: text/html; charset=iso-8859-1 ") (define post-response-body:www.apache.org/ " 405 Method Not Allowed

Method Not Allowed

The requested method POST is not allowed for the URL /.


Apache/2.4.3 (Unix) OpenSSL/1.0.0g Server at www.apache.org Port 80
") (define put-request-headers:www.apache.org/ "PUT / HTTP/1.1 Host: www.apache.org Connection: close ") (define put-response-headers:www.apache.org/ "HTTP/1.1 405 Method Not Allowed Date: Fri, 11 Jan 2013 11:04:34 GMT Server: Apache/2.4.3 (Unix) OpenSSL/1.0.0g Allow: TRACE Content-Length: 313 Connection: close Content-Type: text/html; charset=iso-8859-1 ") (define put-response-body:www.apache.org/ " 405 Method Not Allowed

Method Not Allowed

The requested method PUT is not allowed for the URL /.


Apache/2.4.3 (Unix) OpenSSL/1.0.0g Server at www.apache.org Port 80
") (define delete-request-headers:www.apache.org/ "DELETE / HTTP/1.1 Host: www.apache.org Connection: close ") (define delete-response-headers:www.apache.org/ "HTTP/1.1 405 Method Not Allowed Date: Fri, 11 Jan 2013 11:07:19 GMT Server: Apache/2.4.3 (Unix) OpenSSL/1.0.0g Allow: TRACE Content-Length: 316 Connection: close Content-Type: text/html; charset=iso-8859-1 ") (define delete-response-body:www.apache.org/ " 405 Method Not Allowed

Method Not Allowed

The requested method DELETE is not allowed for the URL /.


Apache/2.4.3 (Unix) OpenSSL/1.0.0g Server at www.apache.org Port 80
") (define options-request-headers:www.apache.org/ "OPTIONS / HTTP/1.1 Host: www.apache.org Connection: close ") (define options-response-headers:www.apache.org/ "HTTP/1.1 200 OK Date: Fri, 11 Jan 2013 11:08:31 GMT Server: Apache/2.4.3 (Unix) OpenSSL/1.0.0g Allow: OPTIONS,GET,HEAD,POST,TRACE Cache-Control: max-age=3600 Expires: Fri, 11 Jan 2013 12:08:31 GMT Content-Length: 0 Connection: close Content-Type: text/html; charset=utf-8 ") ;; This depends on the exact request that we send. I copied this off ;; the console with an "nc" session, so it doesn't include the CR bytes. ;; But that's OK -- we just have to decode the body as an HTTP request ;; and check that it's the same. (define trace-request-headers:www.apache.org/ "TRACE / HTTP/1.1\r Host: www.apache.org\r Connection: close\r \r ") (define trace-response-headers:www.apache.org/ "HTTP/1.1 200 OK\r Date: Fri, 11 Jan 2013 12:36:13 GMT\r Server: Apache/2.4.3 (Unix) OpenSSL/1.0.0g\r Connection: close\r Transfer-Encoding: chunked\r Content-Type: message/http\r \r ") (define trace-response-body:www.apache.org/ "3d\r TRACE / HTTP/1.1\r Host: www.apache.org\r Connection: close\r \r \r 0\r \r ") (define (requests-equal? r1 r2) (and (equal? (request-method r1) (request-method r2)) (equal? (request-uri r1) (request-uri r2)) (equal? (request-version r1) (request-version r2)) (equal? (request-headers r1) (request-headers r2)))) (define (responses-equal? r1 r2) (and (equal? (response-code r1) (response-code r2)) (equal? (response-version r1) (response-version r2)) (equal? (response-headers r1) (response-headers r2)))) (define* (run-with-http-transcript expected-request expected-request-body request-body-encoding response response-body response-body-encoding proc) (let ((reading? #f) (writing? #t) (response-port (open-input-string response)) (response-body-port (open-bytevector-input-port (string->bytevector response-body response-body-encoding)))) (call-with-values (lambda () (open-bytevector-output-port)) (lambda (request-port get-bytevector) (define (put-char c) (unless writing? (error "Port closed for writing")) (put-u8 request-port (char->integer c))) (define (put-string s) (string-for-each put-char s)) (define (flush) (set! writing? #f) (set! reading? #t) (let* ((p (open-bytevector-input-port (get-bytevector))) (actual-request (read-request p)) (actual-body (read-request-body actual-request))) (pass-if "requests equal" (requests-equal? actual-request (call-with-input-string expected-request read-request))) (pass-if "request bodies equal" (equal? (or actual-body #vu8()) (string->bytevector expected-request-body request-body-encoding))))) (define (get-char) (unless reading? (error "Port closed for reading")) (let ((c (read-char response-port))) (if (char? c) c (let ((u8 (get-u8 response-body-port))) (if (eof-object? u8) u8 (integer->char u8)))))) (define (close) (when writing? (unless (eof-object? (get-u8 response-body-port)) (error "Failed to consume all of body")))) (proc (make-soft-port (vector put-char put-string flush get-char close) "rw")))))) (define* (check-transaction method uri request-headers request-body request-body-encoding response-headers response-body response-body-encoding proc #:key (response-body-comparison response-body)) (with-test-prefix (string-append method " " uri) (run-with-http-transcript request-headers request-body request-body-encoding response-headers response-body response-body-encoding (lambda (port) (call-with-values (lambda () (proc uri #:port port)) (lambda (response body) (pass-if "response equal" (responses-equal? response (call-with-input-string response-headers read-response))) (pass-if "response body equal" (equal? (or body "") response-body-comparison)))))))) (check-transaction "GET" "http://www.gnu.org/software/guile/" get-request-headers:www.gnu.org/software/guile/ "" "iso-8859-1" get-response-headers:www.gnu.org/software/guile/ get-response-body:www.gnu.org/software/guile/ "iso-8859-1" http-get) (check-transaction "HEAD" "http://www.gnu.org/software/guile/" head-request-headers:www.gnu.org/software/guile/ "" "iso-8859-1" head-response-headers:www.gnu.org/software/guile/ "" "iso-8859-1" http-head) (check-transaction "POST" "http://www.apache.org/" post-request-headers:www.apache.org/ "" "iso-8859-1" post-response-headers:www.apache.org/ post-response-body:www.apache.org/ "iso-8859-1" http-post) (check-transaction "PUT" "http://www.apache.org/" put-request-headers:www.apache.org/ "" "iso-8859-1" put-response-headers:www.apache.org/ put-response-body:www.apache.org/ "iso-8859-1" http-put) (check-transaction "DELETE" "http://www.apache.org/" delete-request-headers:www.apache.org/ "" "iso-8859-1" delete-response-headers:www.apache.org/ delete-response-body:www.apache.org/ "iso-8859-1" http-delete) (check-transaction "OPTIONS" "http://www.apache.org/" options-request-headers:www.apache.org/ "" "utf-8" options-response-headers:www.apache.org/ "" "utf-8" http-options) (check-transaction "TRACE" "http://www.apache.org/" trace-request-headers:www.apache.org/ "" "iso-8859-1" trace-response-headers:www.apache.org/ trace-response-body:www.apache.org/ "iso-8859-1" http-trace #:response-body-comparison ;; The body will be message/http, which is logically a sequence of ;; bytes, not characters. It happens that iso-8859-1 can encode our ;; body and is compatible with the headers as well. (string->bytevector trace-request-headers:www.apache.org/ "iso-8859-1"))