3

目前对我来说有一个无法解释的行为,感谢任何线索。

背景

我通过 PHP 内置开发 webserver 有一个本地运行的 wordpress 实例php -S localhost:8000 -t /doc/root/wordpress。该网站有效,我可以curl "http://localhost:8000/"成功获取它,我也可以在网络浏览器中打开它。

但简单的程序,如:

(drakma:http-request "http://localhost:8000/")

或者

(dexador:get "http://localhost:8000/")

——都失败了。

drakma回溯失败:

Condition USOCKET:CONNECTION-REFUSED-ERROR was signalled.
   [Condition of type USOCKET:CONNECTION-REFUSED-ERROR]

Restarts:
 0: [RETRY] Retry SLIME REPL evaluation request.
 1: [*ABORT] Return to SLIME's top level.
 2: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1004CC9B93}>)

Backtrace:
  0: (USOCKET::HANDLE-CONDITION #<SB-BSD-SOCKETS:CONNECTION-REFUSED-ERROR {100435B3A3}> #<USOCKET:STREAM-USOCKET {100435AE33}>)
  1: (SB-KERNEL::%SIGNAL #<SB-BSD-SOCKETS:CONNECTION-REFUSED-ERROR {100435B3A3}>)
  2: (ERROR SB-BSD-SOCKETS:CONNECTION-REFUSED-ERROR :ERRNO 61 :SYSCALL "connect")
  3: (SB-BSD-SOCKETS:SOCKET-ERROR "connect" 61)
  4: (SB-BSD-SOCKETS::CALL-WITH-SOCKET-ADDR #<SB-BSD-SOCKETS:INET-SOCKET 127.0.0.1:49431, fd: 16 {100435AD23}> (#(127 0 0 1) 8000) #<CLOSURE (FLET SB-BSD-SOCKETS::WITH-SOCKET-ADDR-THUNK :IN SB-BSD-SOCKETS:..
  5: ((:METHOD SB-BSD-SOCKETS:SOCKET-CONNECT (SB-BSD-SOCKETS:SOCKET)) #<SB-BSD-SOCKETS:INET-SOCKET 127.0.0.1:49431, fd: 16 {100435AD23}> #(127 0 0 1) 8000) [fast-method]
  6: ((FLET "WITHOUT-INTERRUPTS-BODY-22" :IN USOCKET:SOCKET-CONNECT))
  7: (USOCKET:SOCKET-CONNECT "localhost" 8000 :PROTOCOL :STREAM :ELEMENT-TYPE FLEXI-STREAMS:OCTET :TIMEOUT 20 :DEADLINE NIL :NODELAY :IF-SUPPORTED :LOCAL-HOST NIL :LOCAL-PORT NIL)
  8: (DRAKMA:HTTP-REQUEST #<PURI:URI http://localhost:8000/>)
  9: (SB-INT:SIMPLE-EVAL-IN-LEXENV (DRAKMA:HTTP-REQUEST "http://localhost:8000/") #<NULL-LEXENV>)
 10: (EVAL (DRAKMA:HTTP-REQUEST "http://localhost:8000/"))
 11: (SWANK::EVAL-REGION "(drakma:http-request \"http://localhost:8000/\") ..)
 12: ((LAMBDA NIL :IN SWANK-REPL::REPL-EVAL))
 13: (SWANK-REPL::TRACK-PACKAGE #<CLOSURE (LAMBDA NIL :IN SWANK-REPL::REPL-EVAL) {100435A53B}>)
 14: (SWANK::CALL-WITH-RETRY-RESTART "Retry SLIME REPL evaluation request." #<CLOSURE (LAMBDA NIL :IN SWANK-REPL::REPL-EVAL) {100435A4DB}>)
 15: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<CLOSURE (LAMBDA NIL :IN SWANK-REPL::REPL-EVAL) {100435A4BB}>)
 16: (SWANK-REPL::REPL-EVAL "(drakma:http-request \"http://localhost:8000/\") ..)
 17: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK-REPL:LISTENER-EVAL "(drakma:http-request \"http://localhost:8000/\") ..)
 18: (EVAL (SWANK-REPL:LISTENER-EVAL "(drakma:http-request \"http://localhost:8000/\") ..)
 19: (SWANK:EVAL-FOR-EMACS (SWANK-REPL:LISTENER-EVAL "(drakma:http-request \"http://localhost:8000/\") ..)
 20: (SWANK::PROCESS-REQUESTS NIL)
 21: ((LAMBDA NIL :IN SWANK::HANDLE-REQUESTS))
 22: ((LAMBDA NIL :IN SWANK::HANDLE-REQUESTS))
 23: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<CLOSURE (LAMBDA NIL :IN SWANK::HANDLE-REQUESTS) {1004CD008B}>)
 24: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/Users/ihar/.roswell/lisp/slime/2019.02.02/swank/sbcl.lisp") #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<CLOSURE (LAMBDA NIL :IN SWANK::HANDLE-REQUESTS) {..
 25: (SWANK::CALL-WITH-BINDINGS ((*STANDARD-INPUT* . #<SWANK/GRAY::SLIME-INPUT-STREAM {1004BC9E93}>)) #<CLOSURE (LAMBDA NIL :IN SWANK::HANDLE-REQUESTS) {1004CD00AB}>)
 26: (SWANK::HANDLE-REQUESTS #<SWANK::MULTITHREADED-CONNECTION {10079AA873}> NIL)
 27: ((FLET SB-UNIX::BODY :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
 28: ((FLET "WITHOUT-INTERRUPTS-BODY-4" :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
 29: ((FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
 30: ((FLET "WITHOUT-INTERRUPTS-BODY-1" :IN SB-THREAD::CALL-WITH-MUTEX))
 31: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE) {3A67D6B}> #<SB-THREAD:MUTEX "thread result lock" owner: #<SB-THREAD:THREAD "..
 32: (SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE #<SB-THREAD:THREAD "repl-thread" RUNNING {1004CC9B93}> NIL #<CLOSURE (LAMBDA NIL :IN SWANK-REPL::SPAWN-REPL-THREAD) {1004CC9B3B}> NIL)
 33: ("foreign function: call_into_lisp")
 34: ("foreign function: new_thread_trampoline")
 35: ("foreign function: _pthread_body")
 36: ("foreign function: _pthread_body")
 37: ("foreign function: thread_start")

有趣的是,如果我将 URI 更改为 Internet 上的任何其他 URI:

(drakma:http-request "https://stackoverflow.com")

- 然后它工作正常。

所以问题可能出在我的本地机器和本地 php-server 的上下文中。这些简单的函数调用可能有什么问题?

我的笔记

  • 在回溯中,我看到了这条线(USOCKET:SOCKET-CONNECT "localhost" 8000 :PROTOCOL :STREAM :ELEMENT-TYPE FLEXI-STREAMS:OCTET :TIMEOUT 20 :DEADLINE NIL :NODELAY :IF-SUPPORTED :LOCAL-HOST NIL :LOCAL-PORT NIL)。键:local-host:local-port都是nil。可能这就是问题所在,因为根据usocket 规范,这些参数负责调用bind()本地地址(它与调用非本地地址有什么不同吗?)。

  • 我也没有在规范中找到drakma:http-request任何特殊参数来指定我正在请求本地服务器。根据示例https://edicl.github.io/drakma/#ex-basic-auth,请求任何 URI 都很简单,并且没有任何“本地地址”与非本地的区别。

加起来

  • 为什么请求“ http://localhost:8000 ”不适用于drakmaor dexador。是否有人可以确认本地 Web 服务器的相同行为?

  • bind()对于本地和非本地地址,系统调用是否有所不同?


PS我已经问过类似的问题,首先似乎问题出在旧软件版本上。现在我发现了问题的更多细节并改写了它,所以我在这里提出另一个问题。


更新 1

也许,问题与用于开发的特定 PHP 内置网络服务器有关,因为该问题只能通过 PHP 网络服务器 + SBCL + Drakma 重现。但是 PHP 网络服务器可以很好地用于curlGo 客户端、网络浏览器。

PHP版本:

PHP 7.3.1 (cli) (built: Jan 10 2019 13:16:34) (NTS) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.1, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.3.1,版权所有 (c) 1999-2018,由 Zend Technologies 提供

-- 随brew install php.

重现步骤

服务器:

php -S localhost:7070

然后与客户一起尝试:

curl "http://localhost:7070"

-- 工作正常(状态码 404 预期并收到)。

语言:

(drakma:http-request "http://localhost:7070")

-- 失败(状态码 404 是预期的,但connection refused被返回)。

4

1 回答 1

2

谁想要详细信息,有一个讨论,Stas Boukarev 帮助调试了这个问题。

运行会在我的计算机php -S localhost:7070上启动一个侦听ipv6地址的服务器,因此在这种情况下请求ipv4地址127.0.0.1:7070不起作用。

因此,服务器必须以明确的ipv4地址启动php -S 127.0.0.1:7070才能正常工作。

于 2019-02-15T14:57:37.327 回答