Часть II
Прост в понимании
DELETE /users/dimastark/posts/1
Удалить пост №1 пользователя dimastark
Прост в понимании
DELETE /users/dimastark/posts/1
Удалить пост №1 пользователя dimastark
Прост в понимании
DELETE /users/dimastark/posts/1
Удалить пост №1 пользователя dimastark
Прост в понимании
DELETE /users/dimastark/posts/1
Удалить пост №1 пользователя dimastark
Прост в понимании
DELETE /users/dimastark/posts/1
Удалить пост №1 пользователя dimastark
Прост в понимании
DELETE /users/dimastark/posts/1
Удалить пост №1 пользователя dimastark
notes
users
├─ dimastark
│ ├─ comments
│ └─ posts
│ ├─ 1
│ └─ 2
└─ gogoleff
Переиспользует HTTP
DELETE /users/dimastark/posts/1
Переиспользует HTTP
// Семантичные методы
DELETE /users/dimastark/posts/1
// Семантичные коды ответа
200 OK
401 Unauthorized
403 Forbidden
404 Not found
500 Internal Server Error
Переиспользует HTTP
Не спецификация, а набор рекомендаций
Не спецификация, а набор рекомендаций
GET /search?text=идемпотентность
Сложная фильтрация и поиск
GET /users?parameter1=value1¶meter2=value2¶meter3=...
POST /users/search
{
"parameter1": "value1",
"parameter2": "value2",
"parameter3": "value3"
}
Сложно мыслить ресурсами
Я создал (POST) себя в университете, обновил (PATCH) знания студентов лекцией и удалил (DELETE) себя из аудитории.
Я пришел в университет, рассказал лекцию студентам и вышел из аудитории.
/v1/users/dimastark → /v2/users/dimastark
/* SearchRequest содержит поисковый запрос,
* а также настройки пагинации */
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 results_per_page = 3;
}
/* SearchRequest содержит поисковый запрос,
* а также настройки пагинации */
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 results_per_page = 3;
}
double, float,
int32, int64, uint32, uint64, sint32, sint64,
bool, string, bytes
/* SearchRequest содержит поисковый запрос,
* а также настройки пагинации */
message SearchRequest {
string query = 1; // Идентификатор поля
int32 page_number = 2; // Уникален
int32 results_per_page = 3; // Не меняется со временем
}
message SearchReply {
repeated Document items = 1;
}
message Document {
map<string, int32> occurrence_counts = 1;
}
message SearchReply {
repeated Document items = 1;
}
message Document {
map<string, int32> occurrence_counts = 1;
}
message SearchReply {
repeated Document items = 1;
}
message Document {
map<string, int32> occurrence_counts = 1;
}
service Searcher {
rpc Search (SearchRequest) returns (SearchReply);
}
service Searcher {
rpc Search (SearchRequest) returns (SearchReply);
}
service Searcher {
rpc Search (SearchRequest) returns (SearchReply);
}
# Генерируем серверный и клиентский код
protoc
--plugin=protoc-gen-grpc=grpc_tools_node_protoc_plugin
--js_out="import_style=commonjs:./protos"
--grpc_out=./protos
search.proto
# Генерируем серверный и клиентский код
protoc
--plugin=protoc-gen-grpc=grpc_tools_node_protoc_plugin
--js_out="import_style=commonjs:./protos"
--grpc_out=./protos
search.proto
# Генерируем серверный и клиентский код
protoc
--plugin=protoc-gen-grpc=grpc_tools_node_protoc_plugin
--js_out="import_style=commonjs:./protos"
--grpc_out=./protos
search.proto
# Генерируем серверный и клиентский код
protoc
--plugin=protoc-gen-grpc=grpc_tools_node_protoc_plugin
--js_out="import_style=commonjs:./protos"
--grpc_out=./protos
search.proto
# Генерируем серверный и клиентский код
protoc
--plugin=protoc-gen-grpc=grpc_tools_node_protoc_plugin
--js_out="import_style=commonjs:./protos"
--grpc_out=./protos
search.proto
# Генерируем тайпинги
protoc
--plugin=protoc-gen-ts=protoc-gen-ts
--ts_out=./protos
search.proto
# Генерируем тайпинги
protoc
--plugin=protoc-gen-ts=protoc-gen-ts
--ts_out=./protos
search.proto
# Генерируем тайпинги
protoc
--plugin=protoc-gen-ts=protoc-gen-ts
--ts_out=./protos
search.proto
import grpc from 'grpc';
import { SearchRequest, SearchReply } from './protos/search_pb';
import { ISearcherServer } from './protos/search_grpc_pb';
class SearcherServiceImpl implements ISearcherServer {
search(
call: grpc.ServerUnaryCall<SearchRequest>,
callback: grpc.sendUnaryData<SearchReply>
) {
...
}
}
import grpc from 'grpc';
import { SearchRequest, SearchReply } from './protos/search_pb';
import { ISearcherServer } from './protos/search_grpc_pb';
class SearcherServiceImpl implements ISearcherServer {
search(
call: grpc.ServerUnaryCall<SearchRequest>,
callback: grpc.sendUnaryData<SearchReply>
) {
...
}
}
import grpc from 'grpc';
import { SearchRequest, SearchReply } from './protos/search_pb';
import { ISearcherServer } from './protos/search_grpc_pb';
class SearcherServiceImpl implements ISearcherServer {
search(
call: grpc.ServerUnaryCall<SearchRequest>,
callback: grpc.sendUnaryData<SearchReply>
) {
...
}
}
import grpc from 'grpc';
import { SearchRequest, SearchReply } from './protos/search_pb';
import { ISearcherServer } from './protos/search_grpc_pb';
class SearcherServiceImpl implements ISearcherServer {
search(
call: grpc.ServerUnaryCall<SearchRequest>,
callback: grpc.sendUnaryData<SearchReply>
) {
...
}
}
import grpc from 'grpc';
import { SearcherService } from './protos/search_grpc_pb';
const server = new grpc.Server();
server.addService(SearcherService, new SearcherServiceImpl());
server.bind(
'0.0.0.0:50051',
grpc.ServerCredentials.createInsecure()
);
server.start();
import grpc from 'grpc';
import { SearcherService } from './protos/search_grpc_pb';
const server = new grpc.Server();
server.addService(SearcherService, new SearcherServiceImpl());
server.bind(
'0.0.0.0:50051',
grpc.ServerCredentials.createInsecure()
);
server.start();
import grpc from 'grpc';
import { SearcherService } from './protos/search_grpc_pb';
const server = new grpc.Server();
server.addService(SearcherService, new SearcherServiceImpl());
server.bind(
'0.0.0.0:50051',
grpc.ServerCredentials.createInsecure()
);
server.start();
import grpc from 'grpc';
import { SearcherService } from './protos/search_grpc_pb';
const server = new grpc.Server();
server.addService(SearcherService, new SearcherServiceImpl());
server.bind(
'0.0.0.0:50051',
grpc.ServerCredentials.createInsecure()
);
server.start();
import grpc from 'grpc';
import { SearcherService } from './protos/search_grpc_pb';
const server = new grpc.Server();
server.addService(SearcherService, new SearcherServiceImpl());
server.bind(
'0.0.0.0:50051',
grpc.ServerCredentials.createInsecure()
);
server.start();
message Person {
int32 id = 1;
string name = 2;
string email = 3;
}