2013-05-22 11 views
13

Mi sento come se mi mancasse qualcosa, ma dopo aver esaminato i documenti per la rete/url e curiosando in generale, non ero in grado di capire un modo per emettere una richiesta GET dal prompt interattivo. Fondamentalmente, voglio imitare il mio flusso di lavoro pitone per rovistando un sito web:Emettere un HTTP GET da REPL in Racket

response = urlopen("http://www.someurl.com") 

è questo fattibile in Racket?

risposta

12

Utilizzando call/input-url ha alcuni vantaggi:

  • Non è necessario chiudere la porta da soli.
  • La porta è chiusa anche se c'è un'eccezione.
  • Il terzo argomento è (input-port? -> any/c), ovvero una funzione che accetta uno input-port e restituisce nulla. Oltre a una funzione scritta dall'utente, questa potrebbe essere una funzione già definita come port->string, read-html-as-xml e così via.

Ad esempio:

(call/input-url (string->url "http://www.google.com/") 
       get-pure-port 
       port->string) 

Nota: Mentre stavo scrivendo questa risposta, ho notato che Oscar ha modificato il proprio fare redirect. La mia modifica simile sarebbe:

(call/input-url (string->url "http://www.google.com/") 
       (curry get-pure-port #:redirections 4) 
       port->string) 

Naturalmente, in entrambi i casi è ancora abbastanza verbose di digitare spesso al REPL. Quindi il suggerimento di Óscar per definire la tua funzione url-open è buona. L'implementazione utilizzando call/input-url sarebbe preferibile, penso.

+1

Esiste un modo per estrarre il codice di stato oltre all'analisi delle intestazioni "a mano"? Sono sorpreso del fatto che non sono riuscito a trovare alcuna funzione di aiuto per farlo, sia nella racchetta propriamente detta, sia nella tua libreria http. – offby1

+0

Mi spiace di non aver nemmeno notato il tuo commento fino ad ora! La mia http lib ha delle funzioni per farlo: https://github.com/greghendershott/http/blob/master/http/head.rkt#L22-L45 –

7

Prova questo:

(require net/url) 

(define input (get-pure-port (string->url "http://www.someurl.com"))) 
(define response (port->string input)) 
(close-input-port input) 

Ora la variabile response conterrà la risposta HTTP dal server. Ancora meglio, imballare quanto sopra in un procedimento, noto anche che ho aggiunto un numero massimo di reindirizzamenti consentiti:

(define (urlopen url) 
    (let* ((input (get-pure-port (string->url url) #:redirections 5)) 
     (response (port->string input))) 
    (close-input-port input) 
    response)) 

(urlopen "http://www.someurl.com") ; this will return the response 

EDIT:

Seguendo @ eccellenti consigli di GregHendershott (vedere la sua risposta per i dettagli), ecco un altro modo più robusto per implementare la funzionalità desiderata:

(define (urlopen url) 
    (call/input-url 
    (string->url url) 
    (curry get-pure-port #:redirections 5) 
    port->string))