我正在使用SBCL、Emacs和Slime.此外,我正在使用德克萨多图书馆.

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

其他人将返回HTML:

(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>
"

将结果存储在变量中后,使用:

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 

我想创建一个函数来判断输出是JSON还是HTML.因此,我做了这个功能:

(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")))

它的工作原理是:

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

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

然而,我的解决方案在我看来是丑陋的.最初,我try 使用handle-case并将答案序列化为JSON.如果成功,它将是一个JSON.如果失败,函数会将对象视为HTML.但事情进展不顺利,因为我不精通handle-case种语法.

你能想出一个替代方案来实现这个目标吗?也许用handle-case

推荐答案

@伊格尼斯·瓦伦斯是对的,你需要使用Content-Type号标题.要更新代码还有一些工作要做.

  1. 使用defparameterDexador响应的一部分是discarded

如果在REPL中调用函数dex:get,它将返回4个值:

* (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

使用defparameter时,变量中只存储第一个值.

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

保存所有值的一种方法是使用函数MULTIPLE-VALUE-LIST

* (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
  1. 从响应中读取Content-Type标题

可以编写一个函数,根据DESTRUCTURING-BIND宏从HTTP头中获取字段.

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

该功能的使用非常简单:

* (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"

Html相关问答推荐

如何防止SVG图标出现断行?

将表格背景图像置于行背景 colored颜色 之上

如何删除FONT创建的文本下方的空格

如何从通过 find-each 方法(在 Rails 应用程序中)生成的列表创建下拉菜单?

为什么 html 元素的 max-width 和 width 一起工作?

如何保持块扩展以填充视口?

并排放置两个 div,同时 div2 环绕 div1

图像如何能达到 HTML 表格的全宽?

不完整的悬停

子 div 在父 div 中溢出

如何使用 CSS 和 HTML 将文本放入图像中?

如何使用 CSS Flex 设计一个导航栏,其中一组项目左对齐而另一组项目右对齐?

将 div 放在图片旁边而不是下方

需要禁用聚焦输入的工具提示(jquery)

Primeng浮动标签溢出管理

弹出窗口溢出溢出:自动,我不明白为什么

无法从社交栏中 Select 选项

列宽等于最宽列宽度的无界容器

动态使用时波浪号不转换为绝对路径

更改包含图标高度的 div