GOOGLE ADS

Montag, 18. April 2022

Wie identifiziert man die Ausgabe von dex:get als JSON oder HTML in Common Lisp?

Ich verwende SBCL, Emacs und Slime. Außerdem verwende ich die Bibliothek Dexador. Somit kann ich HTTP-Anfragen ausführen. Einige von ihnen geben JSON zurück:

CL-USER> (dex:get "http://ip.jsontest.com/")
"{\"ip\": \"179.183.248.207\"}

Andere geben HTML zurück:

(dex:get "https://ambrevar.xyz/")
"<!DOCTYPE html>
<html lang=\"en\">
<head>
<!-- 2021-12-29 -->
<meta charset=\"utf-8\">
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">
<title>&lrm;</title>
<meta name=\"generator\" content=\"Org mode\">
<meta name=\"author\" content=\"root\">
<link rel=\"stylesheet\" type=\"text/css\" href=\"../dark.css\">
<link rel=\"icon\" type=\"image/x-icon\" href=\"../logo.png\">
</head>
<body>
<div id=\"content\">
<div id=\"outline-container-org4051da4\" class=\"outline-2\">
<h2 id=\"org4051da4\">Contact</h2>
<div class=\"outline-text-2\" id=\"text-org4051da4\">
<ul class=\"org-ul\">
<li>Email: <a href=\"mailto:mail@ambrevar.xyz\">mail@ambrevar.xyz</a></li>
<li>PGP: <a href=\"ambrevar.asc\">0x9BDCF497A4BBCC7F</a></li>
</ul>
</div>
</div>
</div>
</body>
</html>
"

Nach dem Speichern des Ergebnisses in Variablen mit:

CL-USER> (defparameter html-response (dex:get "https://ambrevar.xyz/"))
HTML-RESPONSE
CL-USER> (defparameter json-response (dex:get "http://ip.jsontest.com/"))
JSON-RESPONSE

Ich möchte eine Funktion erstellen, um zu überprüfen, ob die Ausgabe JSON oder HTML ist. Daher habe ich diese Funktion:

(defun html-or-json (response)
"Check it the server response is HTML or JSON data."
(cond ((null response) nil)
((equal (subseq response 0 1) "<") "html")
(t "json")))

Es klappt:

CL-USER> (html-or-json json-response)
"json"
CL-USER> (html-or-json html-response)
"html"

Meine Lösungen erscheinen mir jedoch hässlich. Zunächst habe ich versucht, handle-casedie Antwort als JSON zu verwenden und zu serialisieren. Wenn es funktionieren würde, wäre es ein JSON. Wenn dies fehlschlägt, würde die Funktion das Objekt als HTML betrachten. Aber die Dinge liefen nicht gut, da ich mit der handle-caseSyntax nicht vertraut bin.

Fällt Ihnen eine Alternative ein, um dieses Ziel zu erreichen? Vielleicht mit handle-case?


Lösung des Problems

@ignis volens hat Recht, Sie müssen den Content-TypeHeader verwenden. Es gibt einige Arbeit, um den Code zu aktualisieren.

  • Mit defparameterwird ein Teil der DexadorAntwort verworfen

  • Wenn die Funktion dex:getin der REPL aufgerufen wird, gibt sie 4 Werte zurück:

    * (dex:get "http://ip.jsontest.com/")
    "{\"ip\": \"xx.xx.xx.xxx\"} ;; value 1: IP address
    "
    200 ;; value 2: HTTP code
    #<HASH-TABLE:TEST EQUAL:COUNT 6 {100A0EA203}>;; value 3: HTTP headers
    #<QURI.URI.HTTP:URI-HTTP http://ip.jsontest.com/>;; value 4: URI

    Bei Verwendung defparametervon wird nur der erste Wert in der Variablen gespeichert.

    * (defparameter response (dex:get "http://ip.jsontest.com/"))
    RESPONSE
    * response
    "{\"ip\": \"xx.xx.xx.xx\"};; value 1: IP address
    "
    *

    Eine Möglichkeit, alle Werte zu speichern, könnte die Verwendung der Funktion MULTIPLE-VALUE-LIST sein

    * (defparameter response (multiple-value-list (dex:get "http://ip.jsontest.com/")))
    RESPONSE
    * response
    ("{\"ip\": \"xx.xx.xx.xx\"} ;; value 1: IP address
    "
    200 ;; value 2: HTTP code
    #<HASH-TABLE:TEST EQUAL:COUNT 6 {100A146813}>;; value 3: HTTP headers
    #<QURI.URI.HTTP:URI-HTTP http://ip.jsontest.com/>);; value 4: URI

  • Lesen Sie den Content-TypeHeader aus der Antwort

  • Man könnte eine Funktion schreiben, um ein Feld aus den HTTP-Headern zu erhalten, basierend auf dem DESTRUCTURING-BIND- Makro.

    (defun get-dex-header (dex-response header)
    (destructuring-bind (raw-response http-code http-headers quri)
    dex-response
    (gethash header http-headers)))

    Die Verwendung der Funktion ist einfach:

    * (defparameter json-response (multiple-value-list (dex:get "http://ip.jsontest.com/")))
    JSON-RESPONSE
    * (get-dex-header json-response "content-type")
    "application/json"
    * (defparameter html-response (multiple-value-list (dex:get "http://bing.com/")))
    HTML-RESPONSE
    (get-dex-header html-response "content-type")
    "text/html; charset=utf-8"

    Keine Kommentare:

    Kommentar veröffentlichen

    Warum werden SCHED_FIFO-Threads derselben physischen CPU zugewiesen, obwohl CPUs im Leerlauf verfügbar sind?

    Lösung des Problems Wenn ich das richtig verstehe, versuchen Sie, SCHED_FIFO mit aktiviertem Hyperthreading ("HT") zu verwenden, ...