http://nodejs.cn/api/http2/note_on_authority_and_host.html
https://cloud.tencent.com/developer/section/1189948
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/User-Agent
:authority
个人理解:可视为host
,表示服务的IP+Port
HTTP/2 要求请求具有 :authority 伪标头或 host 标头。 当直接构建 HTTP/2 请求时首选 :authority,从 HTTP/1 转换时首选 host(例如在代理中)。
如果 :authority 不存在,则兼容性 API 将回退到 host。 有关详细信息,请参阅 request.authority。 但是,如果不使用兼容性 API(或直接使用 req.headers),则需要自己实现任何回退行为。
":authority" 伪头字段包含目标 URI 的部分权限([RFC3986],第 3.2 节)。权限不得包含 "http" 或 "https" scheme URI 的已弃用 "userinfo" 子组件。为了确保可以准确地再现 HTTP/1.1请求行,当从具有源或星号形式的请求目标的 HTTP/1.1 请求进行转换时,必须省略该伪头字段(参见[RFC7230],第 5.3 节)。直接生成 HTTP/2 请求的客户端应该使用 ":authority" 伪头字段而不是 Host 头字段。将 HTTP/2 请求转换为 HTTP/1.1 的网络中间件必须通过复制 ":authority" 伪头字段的值来创建 Host 头字段(如果请求中不存在的话)。
User-Agent 首部包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。
Client metadata:
Header key: user-agent, value: grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)
Client metadata:
Header key: user-agent, value: grpc-go/1.46.2
Client metadata:
Header key: user-agent, value: grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)
Header key: x-forwarded-for, value: 192.168.10.173
Header key: x-forwarded-host, value: 192.168.10.152
Header key: x-forwarded-path, value: /hello.HelloService/SayHello
Header key: x-forwarded-port, value: 8508
Header key: x-forwarded-proto, value: http
Header key: x-real-ip, value: 192.168.10.173
Client metadata:
Header key: user-agent, value: grpc-go/1.46.2
Header key: x-forwarded-for, value: 192.168.10.96
Header key: x-forwarded-host, value: 192.168.10.152
Header key: x-forwarded-path, value: /hello.HelloService/SayHello
Header key: x-forwarded-port, value: 8508
Header key: x-forwarded-proto, value: http
Header key: x-real-ip, value: 192.168.10.96
Client metadata:
Header key: accept, value: application/grpc-web-text
Header key: accept-encoding, value: gzip, deflate
Header key: accept-language, value: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Header key: content-length, value: 9
Header key: origin, value: http://192.168.10.173:8080
Header key: referer, value: http://192.168.10.173:8080/
Header key: user-agent, value: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53
Header key: x-forwarded-for, value: 192.168.10.96
Header key: x-forwarded-host, value: 192.168.10.152
Header key: x-forwarded-path, value: /hello.HelloService/SayHello
Header key: x-forwarded-port, value: 8509
Header key: x-forwarded-prefix, value: /hello
Header key: x-forwarded-proto, value: http
Header key: x-grpc-web, value: 1
Header key: x-real-ip, value: 192.168.10.96
Header key: x-user-agent, value: grpc-web-javascript/0.1
Client metadata:
:authority :: [192.168.10.96:8503]
content-type :: [application/grpc]
grpc-accept-encoding :: [identity, deflate, gzip]
user-agent :: [grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)]
Client metadata:
:authority :: [192.168.10.96:8503]
content-type :: [application/grpc]
user-agent :: [grpc-go/1.46.2]
Client metadata:
x-forwarded-path :: [/hello.HelloService/SayHello]
x-real-ip :: [192.168.10.96]
x-forwarded-for :: [192.168.10.96]
x-forwarded-port :: [8508]
x-forwarded-host :: [192.168.10.152]
content-type :: [application/grpc]
user-agent :: [grpc-go/1.46.2]
:authority :: [192.168.10.96:8503]
x-forwarded-proto :: [http]
Client metadata:
x-forwarded-for :: [192.168.10.173]
content-type :: [application/grpc]
grpc-accept-encoding :: [identity, deflate, gzip]
x-forwarded-port :: [8508]
x-forwarded-host :: [192.168.10.152]
x-real-ip :: [192.168.10.173]
x-forwarded-path :: [/hello.HelloService/SayHello]
user-agent :: [grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)]
:authority :: [192.168.10.96:8503]
x-forwarded-proto :: [http]
Client metadata:
referer :: [http://192.168.10.173:8080/]
x-forwarded-for :: [192.168.10.96]
x-forwarded-path :: [/hello.HelloService/SayHello]
accept-language :: [zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6]
content-length :: [9]
x-forwarded-port :: [8509]
accept :: [application/grpc-web-text]
x-grpc-web :: [1]
x-real-ip :: [192.168.10.96]
x-user-agent :: [grpc-web-javascript/0.1]
accept-encoding :: [gzip, deflate]
x-forwarded-prefix :: [/hello]
user-agent :: [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53]
content-type :: [application/grpc]
origin :: [http://192.168.10.173:8080]
x-forwarded-host :: [192.168.10.152]
:authority :: [192.168.10.96:8503]
x-forwarded-proto :: [http]
获取客户端IP
C++ 服务端
C++直接访问
Go直接访问
C++访问kong
Go访问kong
Grpc-WEB访问网关
C++暂时未实现如何从context获取客户端IP
服务端如果有需要,建议和客户端约定一个Key作为header
Go 服务端
虽然Go
在直接访问时,无法从header
中读取到客户端IP
相关,但通过google.golang.org/grpc/peer
包获取到客户端IP
p, _ := peer.FromContext(ctx)
fmt.Println(p.Addr.String()," ",p.Addr.Network())
Addr()为IP,NetWork为传输方式(tcp/udp/..)
Go metadata
## clinet code
ctx := context.Background()
md := metadata.New(map[string]string{"demo": "go client"})
newCtx2 := metadata.NewOutgoingContext(ctx, md)
- go service:
Client metadata:
user-agent :: [grpc-go/1.46.2]
demo :: [go client]
:authority :: [192.168.10.96:8503]
content-type :: [application/grpc]
- c++ service:
Client metadata:
Header key: go, value: programming
Header key: tour, value: book
Header key: user-agent, value: grpc-go/1.46.2
C++ metadata
## clinet code
grpc::ClientContext context;
context.AddMetadata("demo", "c++ client");
- go:
Client metadata:
:authority :: [192.168.10.96:8503]
content-type :: [application/grpc]
grpc-accept-encoding :: [identity, deflate, gzip]
user-agent :: [grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)]
demo :: [c++ client]
- c++:
Client metadata:
Header key: demo, value: c++ client
Header key: user-agent, value: grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)
syntax = "proto2";
package hello;
option go_package = "./hello";
service HelloService {
rpc SayHello(HelloRequest) returns (HelloResponse);
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
}
message HelloRequest {
optional string greeting = 1;
}
message HelloResponse {
required string reply = 1;
}
/*
GRPC 服务端
*/
package main
import (
"context"
pb "demo_hello/proto/hello"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"log"
"net"
)
type Server struct {
pb.UnimplementedHelloServiceServer
}
func (S *Server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
res := "this is 96"
fmt.Println("Client metadata:")
if headers, ok := metadata.FromIncomingContext(ctx); ok {
for head, val := range headers {
fmt.Println(head, " :: ", val)
}
}
return &pb.HelloResponse{Reply: &res}, nil
}
func main() {
lis, err := net.Listen("tcp", "0.0.0.0:8503")
if err != nil {
log.Fatalf("failed listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterHelloServiceServer(s, &Server{})
log.Printf("Server listen:%v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("Failed Server: %v", err)
}
}
/*
GRPC 客户端
*/
package main
import (
"context"
"flag"
"google.golang.org/grpc/metadata"
"log"
"time"
pb "demo_hello/proto/hello"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
const (
defaultName = "world"
)
var (
addr = flag.String("addr", "192.168.10.96:8503", "the address to connect to")
)
func main() {
flag.Parse()
// Set up a connection to the server.
conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewHelloServiceClient(conn)
// Contact the server and print out its response.
ctx := context.Background()
md := metadata.New(map[string]string{"demo": "go client"})
newCtx2 := metadata.NewOutgoingContext(ctx, md)
ctx, cancel := context.WithTimeout(newCtx2, time.Second)
defer cancel()
name := "ss"
r, err := c.SayHello(ctx, &pb.HelloRequest{Greeting: &name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetReply())
}
/*
GRPC server
*/
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "hello_world/hello_world.grpc.pb.h"
#endif
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using hello::HelloRequest;
using hello::HelloResponse;
using hello::HelloService;
using Service = hello::HelloService::Service;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Service {
Status SayHello(ServerContext *context, const HelloRequest *request, hello::HelloResponse *reply) override {
std::string prefix("Hello ");
// Get the client's initial metadata
std::cout << "Client metadata: " << std::endl;
const std::multimap<grpc::string_ref, grpc::string_ref> metadata = context->client_metadata();
for (auto iter = metadata.begin(); iter != metadata.end(); ++iter) {
std::cout << "Header key: " << iter->first << ", value: ";
// Check for binary value
size_t isbin = iter->first.find("-bin");
if ((isbin != std::string::npos) && (isbin + 4 == iter->first.size())) {
std::cout << std::hex;
for (auto c : iter->second) {
std::cout << static_cast<unsigned int>(c);
}
std::cout << std::dec;
} else {
std::cout << iter->second;
}
std::cout << std::endl;
}
reply->set_reply("173");
return Status::OK;
}
};
void RunServer() {
std::string server_address("0.0.0.0:8503");
GreeterServiceImpl service;
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
int main(int argc, char **argv) {
RunServer();
return 0;
}
/*
GRPC client
*/
//
// Created by mimo on 2022/5/24.
//
#include "iostream"
#include "memory"
#include "grpcpp/grpcpp.h"
#include "hello_world/hello_world.grpc.pb.h"
using namespace std;
using namespace hello;
class HelloClient {
public:
explicit HelloClient(const std::shared_ptr<grpc::Channel> &channel)
: stub_(hello::HelloService::NewStub(channel)) {}
void SayHello() {
grpc::ClientContext context;
context.AddMetadata("demo", "c++ client");
HelloRequest request;
HelloResponse response;
request.set_greeting("dd");
auto res = stub_->SayHello(&context, request, &response);
if (!res.ok()) {
std::cout << "Failed IsConnected alarm server" << std::endl;
return;
}
std::cout << response.reply();
}
private:
std::unique_ptr<hello::HelloService::Stub> stub_;
};
int main(){
HelloClient client(grpc::CreateChannel("192.168.10.96:8503", grpc::InsecureChannelCredentials()));
client.SayHello();
return 0;
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章