Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions examples/features/https/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# HTTPS example

This example demonstrates HTTPS Standard Service in tRPC-Go and provides two
ways to run the client:

- Pure code example (see `client/`).
- YAML-only example (see `clientyaml/`).

The server listens on `9443` with a self-signed certificate (demo only).

## Layout

```
examples/features/https/
├── server/ # Server (9443, https_no_protocol)
├── client/ # Pure code: enable TLS via WithTarget/WithTLS
└── clientyaml/ # YAML-only: enable TLS via YAML
```

## Start the server (9443)

```bash
cd server
go run main.go -conf trpc_go.yaml
```

## Client options

Pick either the pure code client or the YAML-only client.

### Pure code ([client/](./client/))

Explicitly set backend target and TLS in code:

- Case A: `https + ca_cert:none` (insecure).
- Case B: `http + ca_cert:none` (enable TLS via `ca_cert:none`).

Run:

```bash
cd ../client
# Code uses ip://127.0.0.1:9443 + WithTLS(..., "none", ...)
# You will see three logs: A success, B failure (no ca), C success (http+none)
go run main.go
```

Notes (code):

- `protocol: https` alone does not enable TLS; you need a TLS signal:
- `WithTLS("", "", "none", "localhost")`, or
- YAML provides `ca_cert: "none"`/real CA, or
- Port inference (e.g., direct `:9443`).

### YAML-only ([clientyaml/](./clientyaml/))

Three YAML files show common cases:

- `trpc_go.yaml`: `protocol: https` + `ca_cert: "none"`.
- `trpc_go_no_ca.yaml`: `protocol: https`, no `ca_cert`, target port `9443`.
- `trpc_go_http_ca.yaml`: `protocol: http` + `ca_cert: "none"`.

Run:

```bash
cd ../clientyaml
# Case A: protocol:https, no ca_cert (port 9443)
go run main.go -conf trpc_go_no_ca.yaml
# Case B: protocol:http, ca_cert:"none" (port 9443)
go run main.go -conf trpc_go_http_ca.yaml
# Case C: protocol:https, ca_cert:"none" (port 9443)
go run main.go -conf trpc_go.yaml
```

Notes (YAML):

- `dns://host` without port defaults to 80 (no TLS inference).
- Append `:443` (or your TLS port), or
- Provide `ca_cert: "none"`/real CA in YAML.
- Ensure the config is loaded:
- In-service: `trpc.NewServer()` loads automatically.
- Tools: see `clientyaml/main.go` using `LoadGlobalConfig` + `Setup`.

## Expected

- Case A (https, no ca_cert, 9443): success, body `https response body`,
header `reply: https-response-head`.
- Case B (http, ca_cert:none, 9443): success (TLS enabled by `ca_cert:none`).

## FAQ

- Why is `protocol: https` not enough by itself?
- TLS requires a signal (port, CA, or code `WithTLS`).
- Do I have to use 443?
- No. 9443 works in this demo; the key is the target is a TLS service.
- Production tips?
- Provide real `ca_cert` and `tls_server_name` instead of `none`.
162 changes: 162 additions & 0 deletions examples/features/https/client/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
//
//
// Tencent is pleased to support the open source community by making tRPC available.
//
// Copyright (C) 2023 Tencent.
// All rights reserved.
//
// If you have downloaded a copy of the tRPC source code from Tencent,
// please note that tRPC source code is licensed under the Apache 2.0 License,
// A copy of the Apache 2.0 License is included in this file.
//
//

package main

import (
"context"
"net/http"

"trpc.group/trpc-go/trpc-go/client"
"trpc.group/trpc-go/trpc-go/codec"
thttp "trpc.group/trpc-go/trpc-go/http"
"trpc.group/trpc-go/trpc-go/log"
)

func main() {
// Test 1: protocol: https with ca_cert: "none"
log.Info("=== Test 1: protocol: https with ca_cert: none ===")
httpsWithCaCert()

// Test 2: protocol: https without ca_cert (should work with explicit HTTPS)
log.Info("=== Test 2: protocol: https without ca_cert ===")
httpsWithoutCaCert()

// Test 3: protocol: http with ca_cert: "none" (should also work)
log.Info("=== Test 3: protocol: http with ca_cert: none ===")
httpWithCaCert()
}

// httpsWithCaCert sends an HTTPS POST request using explicit HTTPS protocol with ca_cert: "none".
func httpsWithCaCert() {
// Create a ClientProxy with target and TLS enabled via ca_cert: "none".
httpCli := thttp.NewClientProxy("trpc.app.server.stdhttps",
client.WithSerializationType(codec.SerializationTypeNoop),
client.WithCurrentSerializationType(codec.SerializationTypeNoop),
client.WithTarget("ip://127.0.0.1:9443"),
client.WithTLS("", "", "none", "localhost"),
)

// Create a ClientReqHeader with the specified HTTP method (POST)
reqHeader := &thttp.ClientReqHeader{
Method: http.MethodPost,
}

// Add a custom "request" header to the HTTP request header
reqHeader.AddHeader("request", "https-test-with-ca-cert")

// Create ClientRspHeader to store the response header
rspHead := &thttp.ClientRspHeader{}

// Create a Body containing the request data
req := &codec.Body{Data: []byte("Hello, I am HTTPS client with ca_cert!")}

// Create an empty Body to store the response data
rsp := &codec.Body{}

// Send a HTTPS POST request
if err := httpCli.Post(context.Background(), "/v1/hello", req, rsp,
client.WithReqHead(reqHeader),
client.WithRspHead(rspHead),
); err != nil {
log.Errorf("Error getting HTTPS response with ca_cert: %v", err)
return
}

// Get the "reply" field from the HTTP response header
replyHead := rspHead.Response.Header.Get("reply")
log.Infof("HTTPS with ca_cert - Data: \"%s\", Response head: \"%s\"", string(rsp.Data), replyHead)
}

// httpsWithoutCaCert sends an HTTPS POST request using explicit HTTPS protocol without ca_cert.
// This should work if explicit HTTPS is properly implemented.
func httpsWithoutCaCert() {
// Create a ClientProxy with HTTPS but no ca_cert to test behavior.
httpCli := thttp.NewClientProxy("trpc.app.server.stdhttps-no-ca",
client.WithSerializationType(codec.SerializationTypeNoop),
client.WithCurrentSerializationType(codec.SerializationTypeNoop),
client.WithTarget("ip://127.0.0.1:9443"),
)

// Create a ClientReqHeader with the specified HTTP method (POST)
reqHeader := &thttp.ClientReqHeader{
Method: http.MethodPost,
}

// Add a custom "request" header to the HTTP request header
reqHeader.AddHeader("request", "https-test-without-ca-cert")

// Create ClientRspHeader to store the response header
rspHead := &thttp.ClientRspHeader{}

// Create a Body containing the request data
req := &codec.Body{Data: []byte("Hello, I am HTTPS client without ca_cert!")}

// Create an empty Body to store the response data
rsp := &codec.Body{}

// Send a HTTPS POST request
if err := httpCli.Post(context.Background(), "/v1/hello", req, rsp,
client.WithReqHead(reqHeader),
client.WithRspHead(rspHead),
); err != nil {
log.Errorf("Error getting HTTPS response without ca_cert: %v", err)
return
}

// Get the "reply" field from the HTTP response header
replyHead := rspHead.Response.Header.Get("reply")
log.Infof("HTTPS without ca_cert - Data: \"%s\", Response head: \"%s\"", string(rsp.Data), replyHead)
}

// httpWithCaCert sends an HTTPS POST request using HTTP protocol with ca_cert: "none".
// This should work because ca_cert triggers HTTPS inference.
func httpWithCaCert() {
// Create a ClientProxy with HTTP protocol but TLS enabled via ca_cert: "none".
httpCli := thttp.NewClientProxy("trpc.app.server.stdhttps-http-ca",
client.WithSerializationType(codec.SerializationTypeNoop),
client.WithCurrentSerializationType(codec.SerializationTypeNoop),
client.WithTarget("ip://127.0.0.1:9443"),
client.WithTLS("", "", "none", "localhost"),
)

// Create a ClientReqHeader with the specified HTTP method (POST)
reqHeader := &thttp.ClientReqHeader{
Method: http.MethodPost,
}

// Add a custom "request" header to the HTTP request header
reqHeader.AddHeader("request", "http-test-with-ca-cert")

// Create ClientRspHeader to store the response header
rspHead := &thttp.ClientRspHeader{}

// Create a Body containing the request data
req := &codec.Body{Data: []byte("Hello, I am HTTP client with ca_cert!")}

// Create an empty Body to store the response data
rsp := &codec.Body{}

// Send a HTTPS POST request
if err := httpCli.Post(context.Background(), "/v1/hello", req, rsp,
client.WithReqHead(reqHeader),
client.WithRspHead(rspHead),
); err != nil {
log.Errorf("Error getting HTTP response with ca_cert: %v", err)
return
}

// Get the "reply" field from the HTTP response header
replyHead := rspHead.Response.Header.Get("reply")
log.Infof("HTTP with ca_cert - Data: \"%s\", Response head: \"%s\"", string(rsp.Data), replyHead)
}
Loading
Loading