blob: 503405f208b34fdb245c1dfe57a355e3e1af048c [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
Brian Silverman8fce7482020-01-05 13:18:21 -08004
5#include <cstdio>
6
Austin Schuh812d0d12021-11-04 20:16:48 -07007#include "fmt/format.h"
Brian Silverman8fce7482020-01-05 13:18:21 -08008#include "wpi/EventLoopRunner.h"
9#include "wpi/HttpServerConnection.h"
10#include "wpi/UrlParser.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080011#include "wpi/uv/Loop.h"
12#include "wpi/uv/Tcp.h"
13
14namespace uv = wpi::uv;
15
16class MyHttpServerConnection : public wpi::HttpServerConnection {
17 public:
18 explicit MyHttpServerConnection(std::shared_ptr<uv::Stream> stream)
19 : HttpServerConnection(stream) {}
20
21 protected:
22 void ProcessRequest() override;
23};
24
25void MyHttpServerConnection::ProcessRequest() {
Austin Schuh812d0d12021-11-04 20:16:48 -070026 fmt::print(stderr, "HTTP request: '{}'\n", m_request.GetUrl());
Brian Silverman8fce7482020-01-05 13:18:21 -080027 wpi::UrlParser url{m_request.GetUrl(),
28 m_request.GetMethod() == wpi::HTTP_CONNECT};
29 if (!url.IsValid()) {
30 // failed to parse URL
31 SendError(400);
32 return;
33 }
34
Austin Schuh812d0d12021-11-04 20:16:48 -070035 std::string_view path;
36 if (url.HasPath()) {
37 path = url.GetPath();
38 }
39 fmt::print(stderr, "path: \"{}\"\n", path);
Brian Silverman8fce7482020-01-05 13:18:21 -080040
Austin Schuh812d0d12021-11-04 20:16:48 -070041 std::string_view query;
42 if (url.HasQuery()) {
43 query = url.GetQuery();
44 }
45 fmt::print(stderr, "query: \"{}\"\n", query);
Brian Silverman8fce7482020-01-05 13:18:21 -080046
47 const bool isGET = m_request.GetMethod() == wpi::HTTP_GET;
Austin Schuh812d0d12021-11-04 20:16:48 -070048 if (isGET && path == "/") {
Brian Silverman8fce7482020-01-05 13:18:21 -080049 // build HTML root page
Austin Schuh812d0d12021-11-04 20:16:48 -070050 SendResponse(200, "OK", "text/html",
51 "<html><head><title>WebServer Example</title></head>"
52 "<body><p>This is an example root page from the webserver."
53 "</body></html>");
Brian Silverman8fce7482020-01-05 13:18:21 -080054 } else {
55 SendError(404, "Resource not found");
56 }
57}
58
59int main() {
60 // Kick off the event loop on a separate thread
61 wpi::EventLoopRunner loop;
62 loop.ExecAsync([](uv::Loop& loop) {
63 auto tcp = uv::Tcp::Create(loop);
64
65 // bind to listen address and port
66 tcp->Bind("", 8080);
67
68 // when we get a connection, accept it and start reading
69 tcp->connection.connect([srv = tcp.get()] {
70 auto tcp = srv->Accept();
Austin Schuh812d0d12021-11-04 20:16:48 -070071 if (!tcp) {
72 return;
73 }
74 std::fputs("Got a connection\n", stderr);
Brian Silverman8fce7482020-01-05 13:18:21 -080075 auto conn = std::make_shared<MyHttpServerConnection>(tcp);
76 tcp->SetData(conn);
77 });
78
79 // start listening for incoming connections
80 tcp->Listen();
81
Austin Schuh812d0d12021-11-04 20:16:48 -070082 std::fputs("Listening on port 8080\n", stderr);
Brian Silverman8fce7482020-01-05 13:18:21 -080083 });
84
85 // wait for a keypress to terminate
86 std::getchar();
87}