}
message AddUrlReply {
// Error code if an error occured.
optional int32 error_code = 1;
// Error mtssage if an error occured.
optional string error_details = 2;
}
service AddUrlService {
// Accepts a URL for submission to the index.
rpc AddUrl(AddUrlRequest) returns (AddUrlReply) {
option deadline = 10.0;
}
}
В файле addurl.proto определены три важных элемента: сообщения AddUrlRequest и AddUrlReply и сервис удаленного вызова процедур (RPC, Remote Procedure) AddUrlService.
Посмотрев на определения сообщения AddUrlRequest, мы видим, что поле url должно быть задано вызывающей стороной, а поле comment не является обязательным.
Точно так же из определения сообщения AddUrlReply следует, что оба поля — error_code и error_details опционально могут быть переданы в ответах сервиса. Мы предполагаем, что в типичном случае, когда URL-адрес успешно принят, эти поля останутся пустыми, чтобы минимизировать объем передаваемых данных. Это одно из правил Google: типичный случай должен работать быстро.
Из определения AddUrlService видно, что сервис содержит единственный метод AddUrl, который принимает AddUrlRequest и возвращает AddUrlReply. По умолчанию вызов метода AddUrl прерывается по тайм-ауту через 10 секунд, если клиент не получил ответа за это время. Реализации интерфейса AddUrlService могут включать в себя сколько угодно систем хранения данных, но для клиентов интерфейса это несущественно, поэтому эти подробности не отражены в файле addurl.proto.
Обозначение '= 1' в полях сообщений не имеет никакого отношения к значениям этих полей. Оно существует для того, чтобы протокол можно было дорабатывать. Например, кто-то захочет добавить поле uri в сообщение AddUrlRequest к уже имеющимся полям. Для этого вносится следующее изменение:
message AddUrlRequest {
required string url = 1; // The URL entered by the user.
optional string comment = 2; // Comments made by the user.
optional string uri = 3; // The URI entered by the user.
}
Но это выглядит довольно глупо — скорее всего, потребуется просто переименовать поле url в uri. Если это число и тип останутся неизменными, сохранится совместимость между старой и новой версией:
message AddUrlRequest {
required string uri = 1; // The URI entered by user.
optional string comment = 2; // Comments made by the user.
}
Написав файл addurl.proto, разработчик переходит к созданию правила сборки proto_library, которое генерирует исходные файлы C++, определяющие сущности из addurl.proto , и компилирует их в статическую библиотеку addurl C++ . С дополнительными параметрами можно сгенерировать исходный код для языков Java и Python.
File: depot/addurl/BUILD
proto_library(name="addurl",
srcs=["addurl.proto"])
Разработчик запускает систему сборки и исправляет все проблемы, обнаруженные ею в addurl.proto и в файле BUILD. Система сборки вызывает компилятор Protocol Buffers, генерирует исходные файлы addurl.pb.h и addurl.pb.cc и статическую библиотеку addurl, которую теперь можно подключить.
Пора писать AddUrlFrontend. Для этого мы объявляем класс AddUrlFrontend в новом файле addurl_frontend.h . Этот код в основном шаблонный.
File: depot/addurl/addurl_frontend.h
#ifndef ADDURL_ADDURL_FRONTEND_H_
#define ADDURL_ADDURL_FRONTEND_H_
// Forward-declaration of dependencies.
class AddUrlService;
class HTTPRequest;
class HTTPReply;
// Frontend for the AddUrl system.
// Accepts HTTP requests from web clients,
// and forwards well-formed requests to the backend.
class AddUrlFrontend {
public:
// Constructor which enables injection of an
// AddUrlService dependency.
explicit AddUrlFrontend(AddUrlService* add_url_service);
~AddUrlFrontend();
// Method invoked by our HTTP server when a request arrives
// for the /addurl resource.
void HandleAddUrlFrontendRequest(const HTTPRequest* http_request,
HTTPReply* http_reply);
private:
AddUrlService* add_url_service_;
// Declare copy constructor and operator= private to prohibit
// unintentional copying of instances of this class .
AddUrlFrontend(const AddUrlFrontend&);
AddUrlFrontend& operator=(const AddUrlFrontend& rhs);
};
#endif // ADDURL_ADDURL_FRONTEND_H_
Продолжая определять классы AddUrlFrontend, разработчик создает файл addurl_frontend.cc , в котором описывает класс AddUrlFrontend. Для экономии места мы опустили часть файла.
File: depot/addurl/addurl_frontend.cc
#include "addurl/addurl_frontend.h"
#include "addurl/addurl.pb.h"
#include "path/to/httpqueryparams.h"
// Functions used by HandleAddUrlFrontendRequest() below, but
// whose definitions are omitted for brevity.
void ExtractHttpQueryParams(const HTTPRequest* http_request,
HTTPQueryParams* query_params);
void WriteHttp200Reply(HTTPReply* reply);
void WriteHttpReplyWithErrorDetails(
HTTPReply* http_reply, const AddUrlReply& add_url_reply);
// AddUrlFrontend constructor that injects the AddUrlService
// dependency.
AddUrlFrontend::AddUrlFrontend(AddUrlService* add_url_service)
: add_url_service_(add_url_service) {
}
// AddUrlFrontend destructor–there's nothing to do here.
AddUrlFrontend::~AddUrlFrontend() {
}
// HandleAddUrlFrontendRequest:
// Handles requests to /addurl by parsing the request,
// dispatching a backend request to an AddUrlService backend,
// and transforming the backend reply into an appropriate
// HTTP reply.
//
Читать дальше
Конец ознакомительного отрывка
Купить книгу