blob: e112d04844938a6308eb2bbfae36707df976b393 [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2018 FIRST. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include <cstdio>
9
10#include "wpi/EventLoopRunner.h"
11#include "wpi/HttpServerConnection.h"
12#include "wpi/UrlParser.h"
13#include "wpi/raw_ostream.h"
14#include "wpi/uv/Loop.h"
15#include "wpi/uv/Tcp.h"
16
17namespace uv = wpi::uv;
18
19class MyHttpServerConnection : public wpi::HttpServerConnection {
20 public:
21 explicit MyHttpServerConnection(std::shared_ptr<uv::Stream> stream)
22 : HttpServerConnection(stream) {}
23
24 protected:
25 void ProcessRequest() override;
26};
27
28void MyHttpServerConnection::ProcessRequest() {
29 wpi::errs() << "HTTP request: '" << m_request.GetUrl() << "'\n";
30 wpi::UrlParser url{m_request.GetUrl(),
31 m_request.GetMethod() == wpi::HTTP_CONNECT};
32 if (!url.IsValid()) {
33 // failed to parse URL
34 SendError(400);
35 return;
36 }
37
38 wpi::StringRef path;
39 if (url.HasPath()) path = url.GetPath();
40 wpi::errs() << "path: \"" << path << "\"\n";
41
42 wpi::StringRef query;
43 if (url.HasQuery()) query = url.GetQuery();
44 wpi::errs() << "query: \"" << query << "\"\n";
45
46 const bool isGET = m_request.GetMethod() == wpi::HTTP_GET;
47 if (isGET && path.equals("/")) {
48 // build HTML root page
49 wpi::SmallString<256> buf;
50 wpi::raw_svector_ostream os{buf};
51 os << "<html><head><title>WebServer Example</title></head>";
52 os << "<body><p>This is an example root page from the webserver.";
53 os << "</body></html>";
54 SendResponse(200, "OK", "text/html", os.str());
55 } else {
56 SendError(404, "Resource not found");
57 }
58}
59
60int main() {
61 // Kick off the event loop on a separate thread
62 wpi::EventLoopRunner loop;
63 loop.ExecAsync([](uv::Loop& loop) {
64 auto tcp = uv::Tcp::Create(loop);
65
66 // bind to listen address and port
67 tcp->Bind("", 8080);
68
69 // when we get a connection, accept it and start reading
70 tcp->connection.connect([srv = tcp.get()] {
71 auto tcp = srv->Accept();
72 if (!tcp) return;
73 wpi::errs() << "Got a connection\n";
74 auto conn = std::make_shared<MyHttpServerConnection>(tcp);
75 tcp->SetData(conn);
76 });
77
78 // start listening for incoming connections
79 tcp->Listen();
80
81 wpi::errs() << "Listening on port 8080\n";
82 });
83
84 // wait for a keypress to terminate
85 std::getchar();
86}