MockServer.php 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <?php
  2. $server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errstr);
  3. if (!$server) {
  4. die("Error: $errstr ($errno)");
  5. }
  6. function send_sse($client, $id, $event, $data, $retry = 3000) {
  7. $sseData = "id: $id\n";
  8. $sseData .= "event: $event\n";
  9. $sseData .= "data: " . json_encode($data) . "\n";
  10. $sseData .= "retry: $retry\n\n"; // The retry comment is optional and should follow client's needs
  11. fwrite($client, $sseData);
  12. fflush($client);
  13. }
  14. while ($client = @stream_socket_accept($server)) {
  15. // 读取请求
  16. $request = fread($client, 1024);
  17. list($headers, $body) = explode("\r\n\r\n", $request, 2);
  18. // 简单解析请求头
  19. $headerLines = explode("\r\n", $headers);
  20. $requestLine = array_shift($headerLines);
  21. preg_match('/\btimeout:\s*true\b/i', $headers, $timeoutMatch);
  22. preg_match('/\b(bodytype):[ ]*([\w\d]+)\b/i', $headers, $bodyTypeMatch);
  23. $bodyType = $bodyTypeMatch[2] ?? null;
  24. preg_match('/^(GET|POST|PUT|DELETE)\s(\/\S*)\sHTTP\/1.1/', $requestLine, $matches);
  25. $method = $matches[1];
  26. $path = $matches[2];
  27. $headerAssoc = [];
  28. foreach ($headerLines as $header) {
  29. list($name, $value) = explode(": ", $header, 2);
  30. $headerAssoc[strtolower($name)] = $value;
  31. }
  32. if (substr($path, 0, 4) === '/sse') {
  33. $responseHeaders = "HTTP/1.1 200 OK\r\n" .
  34. "Content-Type: text/event-stream;charset=UTF-8\r\n" .
  35. "Cache-Control: no-cache\r\n" .
  36. "Connection: keep-alive\r\n";
  37. foreach ($headerAssoc as $name => $value) {
  38. $responseHeaders .= $name . ": " . $value . "\r\n";
  39. }
  40. $responseHeaders .= "\r\n";
  41. fwrite($client, $responseHeaders);
  42. // 刷新缓冲区,确保头部被立刻发送
  43. flush();
  44. // 模拟发送事件流
  45. $count = 0;
  46. while ($count < 5) {
  47. $data = [
  48. "count" => $count
  49. ];
  50. $sseData = "id: sse-test\n";
  51. $sseData .= "event: flow\n";
  52. $sseData .= "data: " . json_encode($data) . "\n";
  53. $sseData .= "retry: 3000\n\n"; // 重试时间可选
  54. fwrite($client, $sseData);
  55. // 再次刷新缓冲区,以确保数据被发送
  56. flush();
  57. // 等待100毫秒
  58. usleep(100000);
  59. $count++;
  60. }
  61. fclose($client);
  62. continue;
  63. }
  64. if ($timeoutMatch) {
  65. // 模拟超时
  66. sleep(5);
  67. $responseHeaders = "HTTP/1.1 500 Internal Server Error\r\n" .
  68. "Content-Type: text/plain\r\n" .
  69. "Connection: close\r\n\r\n";
  70. fwrite($client, $responseHeaders . "Server Timeout");
  71. } else {
  72. $headerAssoc = [];
  73. foreach ($headerLines as $headerLine) {
  74. list($key, $value) = explode(': ', $headerLine, 2);
  75. $headerAssoc[strtolower($key)] = trim($value);
  76. }
  77. // 获取路径和请求方法
  78. preg_match('/^(GET|POST|PUT|DELETE)\s(\/\S*)\sHTTP\/1.1/', $requestLine, $matches);
  79. $method = $matches[1];
  80. $path = $matches[2];
  81. // 构建响应头
  82. $responseHeaders = "HTTP/1.1 200 OK\r\n" .
  83. "Connection: close\r\n" .
  84. "Content-Type: application/json\r\n" .
  85. "x-acs-request-id: A45EE076-334D-5012-9746-A8F828D20FD4\r\n" .
  86. "http-method: $method\r\n" .
  87. "pathname: $path\r\n" .
  88. "raw-body: $body\r\n";
  89. // 构建响应体
  90. $responseBody = "";
  91. echo $bodyType."\n";
  92. switch ($bodyType) {
  93. case 'array':
  94. $responseBody = json_encode(["AppId", "ClassId", "UserId"]);
  95. break;
  96. case 'error':
  97. $responseHeaders = "HTTP/1.1 400 Bad Request\r\n" .
  98. "Connection: close\r\n" .
  99. "Content-Type: application/json\r\n" .
  100. "x-acs-request-id: A45EE076-334D-5012-9746-A8F828D20FD4\r\n" .
  101. "http-method: $method\r\n" .
  102. "pathname: $path\r\n";
  103. $responseBody = json_encode([
  104. "Code" => "error code",
  105. "Message" => "error message",
  106. "RequestId" => "A45EE076-334D-5012-9746-A8F828D20FD4",
  107. "Description" => "error description",
  108. "AccessDeniedDetail" => new stdClass()
  109. ]);
  110. break;
  111. case 'error1':
  112. $responseHeaders = "HTTP/1.1 400 Bad Request\r\n" .
  113. "Connection: close\r\n" .
  114. "Content-Type: application/json\r\n" .
  115. "x-acs-request-id: A45EE076-334D-5012-9746-A8F828D20FD4\r\n" .
  116. "http-method: $method\r\n" .
  117. "pathname: $path\r\n";
  118. $responseBody = json_encode([
  119. "Code" => "error code",
  120. "Message" => "error message",
  121. "RequestId" => "A45EE076-334D-5012-9746-A8F828D20FD4",
  122. "Description" => "error description",
  123. "AccessDeniedDetail" => new stdClass(),
  124. "accessDeniedDetail" => ["test" => 0]
  125. ]);
  126. break;
  127. case 'error2':
  128. $responseHeaders = "HTTP/1.1 400 Bad Request\r\n" .
  129. "Connection: close\r\n" .
  130. "Content-Type: application/json\r\n" .
  131. "x-acs-request-id: A45EE076-334D-5012-9746-A8F828D20FD4\r\n" .
  132. "http-method: $method\r\n" .
  133. "pathname: $path\r\n";
  134. $responseBody = json_encode([
  135. "Code" => "error code",
  136. "Message" => "error message",
  137. "RequestId" => "A45EE076-334D-5012-9746-A8F828D20FD4",
  138. "Description" => "error description",
  139. "accessDeniedDetail" => ["test" => 0]
  140. ]);
  141. break;
  142. default:
  143. $responseBody = json_encode([
  144. "AppId" => "test",
  145. "ClassId" => "test",
  146. "UserId" => 123
  147. ]);
  148. }
  149. fwrite($client, $responseHeaders . "\r\n" . $responseBody);
  150. }
  151. fclose($client);
  152. continue;
  153. }
  154. fclose($server);