Make sure that you can compile and run core tests and read a basic example Writing your first HTTP server.
In this tutorial we will write a service that stores history of translation changes and returns the most recent translations. MongoDB would be used as a database. The service would have the following Rest API:
Like in Writing your first HTTP server we create a component for handling HTTP requests:
Note that the component holds a storages::mongo::PoolPtr - a client to the Mongo. That client is thread safe, you can use it concurrently from different threads and tasks.
In the Translations::InsertNew
function we get the request arguments and form a BSON document for insertion.
There are different ways to form a document, see Formats (JSON, YAML, BSON, ...).
MongoDB queries are just BSON documents. Each mongo document has an implicit _id
field that stores the document creation time. Knowing that, we can use formats::bson::Oid::MakeMinimalFor() to find all the documents that were added after update_time
. Query sorts the documents by modification times (by _id
), so when the results are written into formats::json::ValueBuilder latter writes rewrite previous data for the same key.
See MongoDB for MongoDB hints and more usage samples.
Static configuration of service is quite close to the configuration from Writing your first HTTP server except for the handler and DB:
components_manager:
components:
mongo-tr: # Matches component registration and component retrieval strings
dbconnection: mongodb://localhost:27217/admin
dns-client: # Asynchronous DNS component
fs-task-processor: fs-task-processor
handler-translations:
path: /v1/translations
method: GET,PATCH
task_processor: main-task-processor
server:
# ...
There are more static options for the MongoDB component configuration, all of them are described at components::Mongo.
Finally, we add our component to the components::MinimalServerComponentList(), and start the server with static configuration kStaticConfig
.
To build the sample, execute the following build steps at the userver root directory:
The sample could be started by running make start-userver-samples-mongo_service
. The command would invoke testsuite start target that sets proper paths in the configuration files, prepares and starts the DB, and starts the service.
To start the service manually start the DB server and run ./samples/mongo_service/userver-samples-mongo_service -c </path/to/static_config.yaml>
.
Now you can send a request to your service from another terminal:
$ curl -X PATCH 'http://localhost:8090/v1/translations?key=hello&lang=ru&value=Привки'
$ curl -X PATCH 'http://localhost:8090/v1/translations?key=hello&lang=ru&value=Дратути'
$ curl -X PATCH 'http://localhost:8090/v1/translations?key=hello&lang=ru&value=Здрасьте'
$ curl -s http://localhost:8090/v1/translations?last_update=2021-11-01T12:00:00Z | jq
{
"content": {
"hello": {
"ru": "Дратути"
},
"wellcome": {
"ru": "Здрасьте"
}
},
"update_time": "2021-12-20T10:17:37.249767773+00:00"
}
Functional tests for the service could be implemented using the testsuite. To do that you have to:
See the full example: