1 Star 0 Fork 0

hardstylewyl/GRPC_Samples

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
index.html 12.77 KB
一键复制 编辑 原始数据 按行查看 历史
hardstylewyl 提交于 2025-01-06 20:42 +08:00 . update:补充提交
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>gRPC JSON transcoding</title>
<link rel="stylesheet" href="/lib/bootstrap/dist/bootstrap.min.css" />
<style type="text/css">
.nav-tabs {
margin-bottom: 1em;
}
.alert:empty {
display:none;
}
code {
margin-bottom: 1em;
}
.container {
max-width: 720px;
}
</style>
</head>
<body>
<div class="container">
<main role="main" class="pb-3">
<h1 class="display-4 mb-4 mt-2">gRPC JSON transcoding</h1>
<p>
JSON transcoding allows you call gRPC methods with familiar HTTP concepts:
</p>
<ul>
<li>HTTP verbs</li>
<li>URL parameter binding</li>
<li>JSON requests/responses</li>
</ul>
<p>
RESTful APIs for your ASP.NET Core gRPC services. No duplication!
</p>
<img src="/images/grpc-rest-logo.png" class="img-fluid mb-3" alt="gRPC loves REST" />
<h5 class="mb-3">Try it now</h5>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="unary-tab" data-bs-toggle="tab" data-bs-target="#unary" type="button" role="tab" aria-controls="home" aria-selected="true">Basic GET</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="stream-tab" data-bs-toggle="tab" data-bs-target="#stream" type="button" role="tab" aria-controls="profile" aria-selected="false">Streaming</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="openapi-tab" data-bs-toggle="tab" data-bs-target="#openapi" type="button" role="tab" aria-controls="profile" aria-selected="false">OpenAPI</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="source-tab" data-bs-toggle="tab" data-bs-target="#source" type="button" role="tab" aria-controls="contact" aria-selected="false">View source</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="unary" role="tabpanel" aria-labelledby="unary-tab">
<form id="sendUnary">
<p>
Send a unary request to the Greeter gRPC service. The name is sent as a URL parameter.
</p>
<div class="row gx-2 align-items-center">
<div class="col-auto">
<label class="visually-hidden" for="inlineFormInput">Hello</label>
<input type="text" class="form-control mb-2" id="nameUnary" placeholder="Hello" required>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-2">Send</button>
</div>
</div>
</form>
<div class="alert alert-success" role="alert" id="resultUnary"></div>
</div>
<div class="tab-pane fade" id="stream" role="tabpanel" aria-labelledby="stream-tab">
<form id="sendStream">
<p>
Send a POST request to the Greeter gRPC service. JSON is sent in the request body.
</p>
<div class="row gx-2 align-items-center">
<div class="col-auto">
<label class="visually-hidden" for="inlineFormInput">Hello</label>
<input type="text" class="form-control mb-2" id="nameStream" placeholder="Hello" required>
</div>
<div class="col-auto">
<label class="visually-hidden" for="inlineFormInput">Count</label>
<input type="number" class="form-control mb-2" id="countStream" placeholder="Count" required>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-primary mb-2">Send</button>
</div>
</div>
</form>
<div class="alert alert-success" role="alert" id="resultStream"></div>
</div>
<div class="tab-pane fade" id="openapi" role="tabpanel" aria-labelledby="openapi-tab">
<p>
View OpenAPI schema generated by Swashbuckle and send requests with Swagger UI.
</p>
<p>
<a href="/swagger" target="_blank">Open Swagger UI</a>
</p>
</div>
<div class="tab-pane fade" id="source" role="tabpanel" aria-labelledby="source-tab">
<p>
This website's source code on GitHub:
</p>
<ul>
<li><a href="https://github.com/grpc/grpc-dotnet/blob/master/examples/Transcoder/Proto/greet.proto" target="_blank">Proto/greet.proto</a> - Add <code>google.api.http</code> annotations to map HTTP calls to gRPC.</li>
<li><a href="https://github.com/grpc/grpc-dotnet/blob/master/examples/Transcoder/Server/Server.csproj" target="_blank">Server/Server.csproj</a> - Add <code>Microsoft.AspNetCore.Grpc.JsonTranscoding</code> NuGet package.</li>
<li><a href="https://github.com/grpc/grpc-dotnet/blob/master/examples/Transcoder/Server/Startup.cs" target="_blank">Server/Startup.cs</a> - Register gRPC JSON transcoding with <code>AddJsonTranscoding()</code>.</li>
</ul>
<p>
The service, <a href="https://github.com/grpc/grpc-dotnet/blob/master/examples/Transcoder/Server/Services/GreeterService.cs" target="_blank">Server/Services/GreeterService.cs</a>, is unchanged. gRPC and REST from one service!
</p>
<p>
Find out more about using gRPC JSON transcoding <a href="https://docs.microsoft.com/aspnet/core/grpc/httpapi">here</a>.
</p>
</div>
</div>
</main>
</div>
<script type="text/javascript" src="/lib/bootstrap/dist/bootstrap.bundle.min.js"></script>
<script type="text/javascript">
var nameUnaryInput = document.getElementById('nameUnary');
var unaryForm = document.getElementById('sendUnary');
var resultUnaryText = document.getElementById('resultUnary');
unaryForm.addEventListener('submit', function (event) {
if (unaryForm.checkValidity()) {
resultUnaryText.innerHTML = '';
var url = '/v1/greeter/' + encodeURIComponent(nameUnaryInput.value);
fetch(url).then(function (response) {
response.text().then(function (data) {
resultUnaryText.innerHTML = `<h6>Request</h6>
<p><code>GET ${url}</code></p>
<h6>Response</h6>
<p><code>HTTP/1.1 ${response.status} ${getReasonPhrase(response.status)}</code></p>
<p><code>${htmlEscape(data)}</code></p>
<h6>Result</h6>
<p>${JSON.parse(data).message}</p>`;
});
});
}
event.preventDefault();
event.stopPropagation();
}, false);
var nameStreamInput = document.getElementById('nameStream');
var countStreamInput = document.getElementById('countStream');
var streamForm = document.getElementById('sendStream');
var resultStreamText = document.getElementById('resultStream');
streamForm.addEventListener('submit', function (event) {
resultStreamText.innerHTML = '';
var url = '/v1/greeter';
var content = JSON.stringify({ name: nameStreamInput.value, count: parseInt(countStreamInput.value) });
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: content
}).then(async function (response) {
var reader = response.body.getReader();
var decoder = new TextDecoder('utf-8');
var buffer = '';
var values = [];
let done, value;
while (!done) {
({ value, done } = await reader.read());
if (done) {
displayData(resultStreamText, url, content, response, values, true);
break;
}
buffer += decoder.decode(value, { stream: true });
var lines = buffer.split(/[\r\n]/);
buffer = lines.pop();
values.push(...lines);
displayData(resultStreamText, url, content, response, values, false);
}
});
event.preventDefault();
event.stopPropagation();
}, false);
function displayData(text, url, content, response, values, done) {
text.innerHTML = `<h6>Request</h6>
<p><code>POST ${url}</code></p>
<p><code>${htmlEscape(content)}</code></p>
<h6>Response</h6>
<p><code>HTTP/1.1 ${response.status} ${getReasonPhrase(response.status)}</code></p>
<p><code>${values.map(v => htmlEscape(v) + "<br />").join("")}</code></p>`;
if (done) {
text.innerHTML += `<h6>Result</h6>
<ul>${values.map(v => "<li>" + JSON.parse(v).message + "</li>").join("")}</ul>`;
}
}
function htmlEscape(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/'/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
function getReasonPhrase(statusCode) {
switch (statusCode) {
case (200): return "OK";
case (201): return "Created";
case (202): return "Accepted";
case (203): return "Non Authoritative Information";
case (204): return "No Content";
case (205): return "Reset Content";
case (206): return "Partial Content";
case (207): return "Partial Update OK";
case (300): return "Mutliple Choices";
case (301): return "Moved Permanently";
case (302): return "Moved Temporarily";
case (303): return "See Other";
case (304): return "Not Modified";
case (305): return "Use Proxy";
case (307): return "Temporary Redirect";
case (400): return "Bad Request";
case (401): return "Unauthorized";
case (402): return "Payment Required";
case (403): return "Forbidden";
case (404): return "Not Found";
case (405): return "Method Not Allowed";
case (406): return "Not Acceptable";
case (407): return "Proxy Authentication Required";
case (408): return "Request Timeout";
case (409): return "Conflict";
case (410): return "Gone";
case (411): return "Length Required";
case (412): return "Precondition Failed";
case (413): return "Request Entity Too Large";
case (414): return "Request-URI Too Long";
case (415): return "Unsupported Media Type";
case (416): return "Requested Range Not Satisfiable";
case (417): return "Expectation Failed";
case (418): return "Reauthentication Required";
case (419): return "Proxy Reauthentication Required";
case (422): return "Unprocessable Entity";
case (423): return "Locked";
case (424): return "Failed Dependency";
case (500): return "Server Error";
case (501): return "Not Implemented";
case (502): return "Bad Gateway";
case (503): return "Service Unavailable";
case (504): return "Gateway Timeout";
case (505): return "HTTP Version Not Supported";
case (507): return "Insufficient Storage";
default: return "";
}
}
</script>
</body>
</html>
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/hardstylewyl/grpc_samples.git
git@gitee.com:hardstylewyl/grpc_samples.git
hardstylewyl
grpc_samples
GRPC_Samples
master

搜索帮助