/** * Send an event to the client. * * @param string $message The message payload to be sent. * @param string $event Type of the event. * * @throws \InvalidArgumentException When the given message is not a valid UTF-8 string. */ public function send(string $message, string $event = null) : Awaitable { if (!\preg_match('//u', $message)) { throw new \InvalidArgumentException('SSE messages must be encoded as UTF-8 strings'); } $data = \str_replace("\n", "\ndata: ", $message); if ($event === null) { $event = ''; } else { $event = "event: {$event}\n"; } return $this->channel->send($event . "data: {$data}\n\n"); }
protected function wireMapper(callable $map, Channel $input, int $concurrency = 1) : Channel { $output = new Channel($concurrency * 2); $executor = new Executor($concurrency); $closed = false; $count = 0; $n = 0; $job = null; $job = function () use(&$job, &$count, &$n, &$closed, $executor, $map, $input, $output) { try { if ($this->eof === ($val = (yield $input->receive($this->eof)))) { if (--$count < 1) { $output->close(); } return; } $val = $map($val, $n++); if ($val instanceof \Generator) { $val = (yield from $val); } if (!$closed) { (yield $output->send($val)); $executor->execute($job); } } catch (\Throwable $e) { if (!$closed) { $closed = true; $output->close($e); } } }; for ($i = 0; $i < $concurrency; $i++) { $count++; $executor->execute($job); } return $output; }
/** * Handle an FCGI STDIN record that transfers request body data. * * @param Record $record * @param Channel $incoming */ public function handleStdin(Record $record, Channel $incoming) : \Generator { if (!$this->received) { $this->received = true; $request = $this->buildRequest(); $incoming->send([$this, $request]); } if ($record->data === '') { return $this->body->close(); } return (yield $this->body->send($record->data)); }
/** * Coroutine that parses incoming requests and queues them into the request pipeline. * * @param DuplexStream $socket Stream being used to transmit HTTP messages. * @param Channel $pipeline HTTP request pipeline. * @param HttpRequest $request First HTTP request within the pipeline. */ protected function parseIncomingRequests(HttpDriverContext $context, SocketStream $socket, Channel $pipeline, HttpRequest $request) : \Generator { try { do { $request = $request ?? (yield from $this->parseNextRequest($context, $socket)); $close = $this->shouldConnectionBeClosed($request); (yield $pipeline->send([$request, $close])); (yield ((yield $request->getBody()->getReadableStream()))->getAwaitable()); $request = null; } while (!$close); $pipeline->close(); } catch (\Throwable $e) { $pipeline->close($e); } }