| 1801 | |
| 1802 | |
| 1803 | Future<http::Response> IOSwitchboardServerProcess::attachContainerOutput( |
| 1804 | ContentType acceptType, |
| 1805 | Option<ContentType> messageAcceptType) |
| 1806 | { |
| 1807 | http::Pipe pipe; |
| 1808 | http::OK ok; |
| 1809 | |
| 1810 | ok.headers["Content-Type"] = stringify(acceptType); |
| 1811 | |
| 1812 | // If a client sets the 'Accept' header expecting a streaming response, |
| 1813 | // `messageAcceptType` would always be set and we use it as the value of |
| 1814 | // 'Message-Content-Type' response header. |
| 1815 | ContentType messageContentType = acceptType; |
| 1816 | if (streamingMediaType(acceptType)) { |
| 1817 | CHECK_SOME(messageAcceptType); |
| 1818 | ok.headers[MESSAGE_CONTENT_TYPE] = stringify(messageAcceptType.get()); |
| 1819 | messageContentType = messageAcceptType.get(); |
| 1820 | } |
| 1821 | |
| 1822 | ok.type = http::Response::PIPE; |
| 1823 | ok.reader = pipe.reader(); |
| 1824 | |
| 1825 | // We store the connection in a list and wait for asynchronous |
| 1826 | // calls to `receiveOutput()` to actually push data out over the |
| 1827 | // connection. If we ever detect a connection has been closed, |
| 1828 | // we remove it from this list. |
| 1829 | HttpConnection connection(pipe.writer(), messageContentType); |
| 1830 | auto iterator = outputConnections.insert(outputConnections.end(), connection); |
| 1831 | |
| 1832 | // We use the `startRedirect` promise to indicate when we should |
| 1833 | // begin reading data from our `stdoutFromFd` and `stderrFromFd` |
| 1834 | // file descriptors. If we were started with the `waitForConnection` |
| 1835 | // parameter set to `true`, only set this promise here once the |
| 1836 | // first connection has been established. |
| 1837 | if (!startRedirect.future().isReady()) { |
| 1838 | startRedirect.set(Nothing()); |
| 1839 | } |
| 1840 | |
| 1841 | connection.closed() |
| 1842 | .then(defer(self(), [this, iterator]() { |
| 1843 | // Erasing from a `std::list` only invalidates the iterator of |
| 1844 | // the object being erased. All other iterators remain valid. |
| 1845 | outputConnections.erase(iterator); |
| 1846 | return Nothing(); |
| 1847 | })); |
| 1848 | |
| 1849 | return ok; |
| 1850 | } |
| 1851 | |
| 1852 | |
| 1853 | void IOSwitchboardServerProcess::outputHook( |
nothing calls this directly
no test coverage detected