| 1880 | |
| 1881 | |
| 1882 | Future<Nothing> serve( |
| 1883 | network::Socket socket, |
| 1884 | std::function<Future<Response>(const Request&)>&& f) |
| 1885 | { |
| 1886 | // HTTP serving is implemented by running two loops, a "receive" |
| 1887 | // loop and a "send" loop. The receive loop passes the pipeline of |
| 1888 | // request/responses via a `Queue` to the send loop that is |
| 1889 | // responsible for sending the response back to the client. A `None` |
| 1890 | // passed on the queue signifies that receiving has completed. |
| 1891 | // |
| 1892 | // TODO(benh): Replace this with something like `Stream` that can |
| 1893 | // give us completion semantics without having to encode them with |
| 1894 | // an `Option` like we do here. |
| 1895 | Queue<Option<Item>> pipeline; |
| 1896 | |
| 1897 | Future<Nothing> receiving = |
| 1898 | receive(socket, std::move(f), pipeline) |
| 1899 | .onAny([=]() mutable { |
| 1900 | // Either: |
| 1901 | // |
| 1902 | // (1) An EOF was received. |
| 1903 | // (2) A failure occurred while receiving. |
| 1904 | // (3) Receiving was discarded (likely because serving was |
| 1905 | // discarded). |
| 1906 | // |
| 1907 | // In all cases the best course of action is to signify that |
| 1908 | // no more items will be enqueued on the `pipeline` and in |
| 1909 | // the case of (2) or (3) shutdown the read end of the |
| 1910 | // socket so the client recognizes it can't send any more |
| 1911 | // requests. |
| 1912 | // |
| 1913 | // Note that we don't look at the return value of |
| 1914 | // `Socket::shutdown` because the socket might already be |
| 1915 | // shutdown! |
| 1916 | pipeline.put(None()); |
| 1917 | socket.shutdown(network::Socket::Shutdown::READ); |
| 1918 | }); |
| 1919 | |
| 1920 | Future<Nothing> sending = |
| 1921 | send(socket, pipeline) |
| 1922 | .onAny([=]() mutable { |
| 1923 | // Either: |
| 1924 | // |
| 1925 | // (1) HTTP connection is not meant to be persistent or |
| 1926 | // there are no more items expected in the pipeline. |
| 1927 | // (2) A failure occurred while sending. |
| 1928 | // (3) Sending was discarded (likely because serving was |
| 1929 | // discarded). |
| 1930 | // |
| 1931 | // In all cases the best course of action is to shutdown the |
| 1932 | // socket which will also force receiving to complete. |
| 1933 | // |
| 1934 | // Note that we don't look at the return value of |
| 1935 | // `Socket::shutdown` because the socket might already be |
| 1936 | // shutdown! |
| 1937 | // |
| 1938 | // CAREFUL! We can't shutdown with Shutdown::READ_WRITE |
| 1939 | // because on OSX if the socket is already shutdown with READ |