Skip to content

Commit 31b3312

Browse files
authored
Merge pull request #283 from wravery/boost-beast-sample
Add an HTTP client/server sample with Boost.Beast
2 parents 2382a49 + eeee941 commit 31b3312

23 files changed

+1208
-7
lines changed

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,16 @@ if(GRAPHQL_BUILD_SCHEMAGEN AND GRAPHQL_BUILD_CLIENTGEN)
5252

5353
if(GRAPHQL_UPDATE_SAMPLES)
5454
list(APPEND VCPKG_MANIFEST_FEATURES "update-samples")
55+
56+
option(GRAPHQL_BUILD_HTTP_SAMPLE "Build the HTTP client sample using C++20 coroutines with Boost.Beast/Boost.Asio." ON)
57+
58+
if(GRAPHQL_BUILD_HTTP_SAMPLE)
59+
list(APPEND VCPKG_MANIFEST_FEATURES "http-sample")
60+
endif()
5561
endif()
5662
else()
5763
set(GRAPHQL_UPDATE_SAMPLES OFF CACHE BOOL "Disable regenerating samples." FORCE)
64+
set(GRAPHQL_BUILD_HTTP_SAMPLE OFF CACHE BOOL "Disable regenerating samples." FORCE)
5865
endif()
5966

6067
project(cppgraphqlgen VERSION ${LATEST_VERSION})

README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,9 @@ do that.
127127

128128
### schemagen
129129

130-
I'm using [Boost](https://www.boost.org/doc/libs/1_69_0/more/getting_started/index.html) for `schemagen`:
130+
I'm using [Boost](https://www.boost.org/doc/libs/1_82_0/more/getting_started/index.html) for `schemagen`:
131131

132-
- Command line handling: [Boost.Program_options](https://www.boost.org/doc/libs/1_69_0/doc/html/program_options.html).
132+
- Command line handling: [Boost.Program_options](https://www.boost.org/doc/libs/1_82_0/doc/html/program_options.html).
133133
Run `schemagen -?` to get a list of options. Many of the files in the [samples](samples/) directory were generated
134134
with `schemagen`, you can look at [samples/CMakeLists.txt](samples/CMakeLists.txt) for a few examples of how to call it:
135135
```
@@ -144,8 +144,8 @@ Command line options:
144144
-n [ --namespace ] arg C++ sub-namespace for the generated types
145145
--source-dir arg Target path for the <prefix>Schema.cpp source file
146146
--header-dir arg Target path for the <prefix>Schema.h header file
147-
--no-stubs Generate abstract classes without stub implementations
148-
--separate-files Generate separate files for each of the types
147+
--stubs Unimplemented fields throw runtime exceptions instead
148+
of compiler errors
149149
--no-introspection Do not generate support for Introspection
150150
```
151151

@@ -161,8 +161,7 @@ Windows and UWP shared library targets (the platform triplets which don't end in
161161
### clientgen
162162

163163
The `clientgen` utility is based on `schemagen` and shares the same external dependencies. The command line arguments
164-
are almost the same, except it takes an extra file for the request document and there is no equivalent to `--no-stubs` or
165-
`--separate-files`:
164+
are almost the same, except it takes an extra file for the request document and there is no equivalent to `--stubs`:
166165
```
167166
Usage: clientgen [options] <schema file> <request file> <output filename prefix> <output namespace>
168167
Command line options:
@@ -259,6 +258,12 @@ is no implementation of this schema, it relies entirely generated stubs (created
259258
successfully without defining more than placeholder objects fo the Query, Mutation, and Subscription operations in
260259
[samples/validation/ValidationMock.h](samples/validation/ValidationMock.h). It is used to test the validation logic
261260
with every example or counter-example in the spec in [test/ValidationTests.cpp](test/ValidationTests.cpp).
261+
- [samples/proxy](samples/proxy/) (`GRAPHQL_BUILD_HTTP_SAMPLE=ON`): Generates a `client` and `server` pair of
262+
executables which proxy requests from the `client` to the `server` over HTTP (on port 8080 for localhost). The HTTP
263+
support in both samples comes from [Boost.Beast](https://www.boost.org/doc/libs/1_82_0/libs/beast/doc/html/index.html),
264+
which must be included in your `Boost` installation to build this directory. If you are using `vcpkg`, it will install
265+
the necessary `Boost` components on demand. _Note: This directory uses the Boost Software License because the samples
266+
borrow heavily from examples in the `Boost.Beast` documentation._
262267

263268
# Build and Test
264269

samples/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,19 @@ add_subdirectory(client)
77
add_subdirectory(learn)
88
add_subdirectory(today)
99
add_subdirectory(validation)
10+
11+
if(GRAPHQL_BUILD_HTTP_SAMPLE)
12+
find_package(Boost QUIET)
13+
if(Boost_FOUND)
14+
if(Boost_VERSION VERSION_GREATER_EQUAL "1.81.0")
15+
if(EXISTS "${Boost_INCLUDE_DIR}/boost/beast.hpp")
16+
message(STATUS "Using Boost.Beast ${Boost_VERSION}")
17+
add_subdirectory(proxy)
18+
else()
19+
message(WARNING "GRAPHQL_BUILD_HTTP_SAMPLE requires the Boost.Beast header-only library, but it was not found in ${Boost_INCLUDE_DIR}.")
20+
endif()
21+
else()
22+
message(WARNING "GRAPHQL_BUILD_HTTP_SAMPLE requires the Boost.Beast header-only library >= 1.81.0, but only ${Boost_VERSION} was found in ${Boost_INCLUDE_DIR}.")
23+
endif()
24+
endif()
25+
endif()

samples/learn/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ add_library(star_wars STATIC
1414
StarWarsData.cpp)
1515
target_link_libraries(star_wars PUBLIC learn_schema)
1616
target_include_directories(star_wars PUBLIC star_wars)
17+
target_include_directories(star_wars INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
1718

1819
add_executable(learn_star_wars sample.cpp)
1920
target_link_libraries(learn_star_wars PRIVATE

samples/proxy/CMakeLists.txt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
4+
cmake_minimum_required(VERSION 3.15)
5+
6+
add_subdirectory(query)
7+
add_subdirectory(schema)
8+
9+
add_executable(client client.cpp)
10+
target_link_libraries(client PRIVATE
11+
proxy_schema
12+
proxy_client
13+
graphqljson)
14+
target_include_directories(client PRIVATE
15+
proxy_schema
16+
proxy_client)
17+
18+
add_executable(server server.cpp)
19+
target_link_libraries(server PRIVATE
20+
star_wars
21+
graphqljson)
22+
23+
if(MSVC)
24+
target_compile_options(client PRIVATE "-wd4702")
25+
target_compile_options(server PRIVATE "-wd4702")
26+
endif()
27+
28+
if(WIN32 AND BUILD_SHARED_LIBS)
29+
add_custom_command(OUTPUT copied_sample_dlls
30+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
31+
$<TARGET_FILE:graphqlservice>
32+
$<TARGET_FILE:graphqljson>
33+
$<TARGET_FILE:graphqlpeg>
34+
$<TARGET_FILE:graphqlresponse>
35+
$<TARGET_FILE:graphqlclient>
36+
${CMAKE_CURRENT_BINARY_DIR}
37+
COMMAND ${CMAKE_COMMAND} -E touch copied_sample_dlls
38+
DEPENDS
39+
graphqlservice
40+
graphqljson
41+
graphqlpeg
42+
graphqlresponse
43+
graphqlclient)
44+
45+
add_custom_target(copy_proxy_sample_dlls DEPENDS copied_sample_dlls)
46+
47+
add_dependencies(client copy_proxy_sample_dlls)
48+
add_dependencies(server copy_proxy_sample_dlls)
49+
endif()

samples/proxy/LICENSE

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Portions of the files in this directory are copied from the Boost.Beast
2+
examples, and they fall under the Boost Sofware License:
3+
https://www.boost.org/doc/libs/1_82_0/libs/beast/doc/html/beast/examples.html.
4+
5+
This license text is also available from https://www.boost.org/LICENSE_1_0.txt.
6+
7+
-------------------------------------------------------------------------------
8+
9+
Boost Software License - Version 1.0 - August 17th, 2003
10+
11+
Permission is hereby granted, free of charge, to any person or organization
12+
obtaining a copy of the software and accompanying documentation covered by
13+
this license (the "Software") to use, reproduce, display, distribute,
14+
execute, and transmit the Software, and to prepare derivative works of the
15+
Software, and to permit third-parties to whom the Software is furnished to
16+
do so, all subject to the following:
17+
18+
The copyright notices in the Software and this entire statement, including
19+
the above license grant, this restriction and the following disclaimer,
20+
must be included in all copies of the Software, in whole or in part, and
21+
all derivative works of the Software, unless such copies or derivative
22+
works are solely in the form of machine-executable object code generated by
23+
a source language processor.
24+
25+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27+
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
28+
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
29+
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
30+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31+
DEALINGS IN THE SOFTWARE.

samples/proxy/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# HTTP Proxy Sample
2+
3+
## Dependencies
4+
5+
This sample requires the [Boost.Beast](https://www.boost.org/doc/libs/1_82_0/libs/beast/doc/html/index.html)
6+
header-only library. If you are using [vcpkg](https://github.com/microsoft/vcpkg), it can install that component
7+
for you on-demand. Otherwise, you may need to install it separately if you have a selective installation of
8+
`Boost`.
9+
10+
## Server
11+
12+
The `server` executable listens for HTTP connections on http://127.0.0.1:8080/ (port 8080 of `localhost`). It
13+
is expecting POST requests with a JSON payload in the request body that looks like this:
14+
```json
15+
{
16+
"query": "GraphQL query document goes here",
17+
"operationName": "(optional) GraphQL operation name goes here",
18+
"variables": "(optional) JSON object embedded in a string with GraphQL operation variables"
19+
}
20+
```
21+
22+
It has a single thread accepting requests, and it uses C++20 coroutines. The GraphQL service which actually
23+
resolves the requests is the same Star Wars learning sample in [../learn](../learn/).
24+
25+
## Client
26+
27+
The `client` executable works like most of the other command line samples, it can take a single argument for
28+
the operation name and it will read the GraphQL query document from standard input. It packages the query
29+
parameters in variables for a pre-parsed [query/query.graphql](query/query.graphql), and it implements an
30+
in-proc GraphQL service with the [schema/schema.graphql](schema/schema.graphql) schema using an asynchronous
31+
field resolver. The field resolver packages the parameters into a JSON message and sends it to the `server`
32+
process waiting on http://127.0.0.1:8080/.
33+
34+
When it gets a response, `client` uses the same pre-parsed query in [query/query.graphql](query/query.graphql)
35+
to parse the result and return the JSON document in the field returned from the `server` process.
36+
37+
As long as you start the `server` process first, the behavior of `client` should be almost identical to the
38+
`learn_star_wars` executable sample produced by [../learn](../learn/).

0 commit comments

Comments
 (0)