Compare commits
	
		
			10 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3f3c3a4471 | |||
| 
						 | 
					cee0fde959 | ||
| b122fed3cc | |||
| 
						 | 
					fa00663740 | ||
| 905398dcb6 | |||
| a6dd9c0455 | |||
| c757127453 | |||
| 
						 | 
					b2b24e0a9a | ||
| ea64ce0eab | |||
| b89246b18c | 
							
								
								
									
										28
									
								
								.github/autoapprove.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								.github/autoapprove.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,28 +0,0 @@
 | 
				
			|||||||
name: "autoapprove"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
on:
 | 
					 | 
				
			||||||
  pull_request_target:
 | 
					 | 
				
			||||||
    types: [assigned, opened, synchronize, reopened]
 | 
					 | 
				
			||||||
  workflow_run:
 | 
					 | 
				
			||||||
    workflows: ["prbuild"]
 | 
					 | 
				
			||||||
    types:
 | 
					 | 
				
			||||||
      - completed
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
permissions:
 | 
					 | 
				
			||||||
  pull-requests: write
 | 
					 | 
				
			||||||
  contents: write
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
jobs:
 | 
					 | 
				
			||||||
  autoapprove:
 | 
					 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					 | 
				
			||||||
    steps:
 | 
					 | 
				
			||||||
      - name: approve
 | 
					 | 
				
			||||||
        run: [ "curl -o tea https://dl.gitea.com/tea/main/tea-main-linux-amd64",
 | 
					 | 
				
			||||||
               "chmod +x ./tea",
 | 
					 | 
				
			||||||
               "./tea login add --name unistack --token ${{ secrets.GITHUB_TOKEN }} --url https://git.unistack.org",
 | 
					 | 
				
			||||||
               "./tea pr --repo ${{ github.event.repository.name }}"
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
        if: github.actor == 'vtolstov'
 | 
					 | 
				
			||||||
        id: approve
 | 
					 | 
				
			||||||
        with:
 | 
					 | 
				
			||||||
          github-token: ${{ secrets.GITHUB_TOKEN }}
 | 
					 | 
				
			||||||
							
								
								
									
										94
									
								
								.github/workflows/job_sync.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										94
									
								
								.github/workflows/job_sync.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,94 +0,0 @@
 | 
				
			|||||||
name: sync
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
on:
 | 
					 | 
				
			||||||
  schedule:
 | 
					 | 
				
			||||||
    - cron: '*/5 * * * *'
 | 
					 | 
				
			||||||
  # Allows you to run this workflow manually from the Actions tab
 | 
					 | 
				
			||||||
  workflow_dispatch:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
jobs:
 | 
					 | 
				
			||||||
  sync:
 | 
					 | 
				
			||||||
    if: github.server_url != 'https://github.com'
 | 
					 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					 | 
				
			||||||
    steps:
 | 
					 | 
				
			||||||
    - name: init
 | 
					 | 
				
			||||||
      run: |
 | 
					 | 
				
			||||||
        git config --global user.email "vtolstov <vtolstov@users.noreply.github.com>"
 | 
					 | 
				
			||||||
        git config --global user.name "github-actions[bot]"
 | 
					 | 
				
			||||||
        echo "machine git.unistack.org login vtolstov password ${{ secrets.TOKEN_GITEA }}" >> /root/.netrc
 | 
					 | 
				
			||||||
        echo "machine github.com login vtolstov password ${{ secrets.TOKEN_GITHUB }}" >> /root/.netrc
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: check master
 | 
					 | 
				
			||||||
      id: check_master
 | 
					 | 
				
			||||||
      run: |
 | 
					 | 
				
			||||||
        src_hash=$(git ls-remote https://github.com/${GITHUB_REPOSITORY} refs/heads/master | cut -f1)
 | 
					 | 
				
			||||||
        dst_hash=$(git ls-remote ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} refs/heads/master | cut -f1)
 | 
					 | 
				
			||||||
        echo "src_hash=$src_hash"
 | 
					 | 
				
			||||||
        echo "dst_hash=$dst_hash"
 | 
					 | 
				
			||||||
        if [ "$src_hash" != "$dst_hash" ]; then
 | 
					 | 
				
			||||||
          echo "sync_needed=true" >> $GITHUB_OUTPUT
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          echo "sync_needed=false" >> $GITHUB_OUTPUT
 | 
					 | 
				
			||||||
        fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: sync master
 | 
					 | 
				
			||||||
      if: steps.check_master.outputs.sync_needed == 'true'
 | 
					 | 
				
			||||||
      run: |
 | 
					 | 
				
			||||||
        git clone --filter=blob:none --filter=tree:0 --branch master --single-branch ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} repo
 | 
					 | 
				
			||||||
        cd repo
 | 
					 | 
				
			||||||
        git remote add --no-tags --fetch --track master upstream https://github.com/${GITHUB_REPOSITORY}
 | 
					 | 
				
			||||||
        git pull --rebase upstream master
 | 
					 | 
				
			||||||
        git push upstream master --progress
 | 
					 | 
				
			||||||
        git push origin master --progress
 | 
					 | 
				
			||||||
        cd ../
 | 
					 | 
				
			||||||
        rm -rf repo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: check v3
 | 
					 | 
				
			||||||
      id: check_v3
 | 
					 | 
				
			||||||
      run: |
 | 
					 | 
				
			||||||
        src_hash=$(git ls-remote https://github.com/${GITHUB_REPOSITORY} refs/heads/v3 | cut -f1)
 | 
					 | 
				
			||||||
        dst_hash=$(git ls-remote ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} refs/heads/v3 | cut -f1)
 | 
					 | 
				
			||||||
        echo "src_hash=$src_hash"
 | 
					 | 
				
			||||||
        echo "dst_hash=$dst_hash"
 | 
					 | 
				
			||||||
        if [ "$src_hash" != "$dst_hash" ]; then
 | 
					 | 
				
			||||||
          echo "sync_needed=true" >> $GITHUB_OUTPUT
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          echo "sync_needed=false" >> $GITHUB_OUTPUT
 | 
					 | 
				
			||||||
        fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: sync v3
 | 
					 | 
				
			||||||
      if: steps.check_v3.outputs.sync_needed == 'true'
 | 
					 | 
				
			||||||
      run: |
 | 
					 | 
				
			||||||
        git clone --filter=blob:none --filter=tree:0 --branch v3 --single-branch ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} repo
 | 
					 | 
				
			||||||
        cd repo
 | 
					 | 
				
			||||||
        git remote add --no-tags --fetch --track v3 upstream https://github.com/${GITHUB_REPOSITORY}
 | 
					 | 
				
			||||||
        git pull --rebase upstream v3
 | 
					 | 
				
			||||||
        git push upstream v3 --progress
 | 
					 | 
				
			||||||
        git push origin v3 --progress
 | 
					 | 
				
			||||||
        cd ../
 | 
					 | 
				
			||||||
        rm -rf repo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: check v4
 | 
					 | 
				
			||||||
      id: check_v4
 | 
					 | 
				
			||||||
      run: |
 | 
					 | 
				
			||||||
        src_hash=$(git ls-remote https://github.com/${GITHUB_REPOSITORY} refs/heads/v4 | cut -f1)
 | 
					 | 
				
			||||||
        dst_hash=$(git ls-remote ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} refs/heads/v4 | cut -f1)
 | 
					 | 
				
			||||||
        echo "src_hash=$src_hash"
 | 
					 | 
				
			||||||
        echo "dst_hash=$dst_hash"
 | 
					 | 
				
			||||||
        if [ "$src_hash" != "$dst_hash" ]; then
 | 
					 | 
				
			||||||
          echo "sync_needed=true" >> $GITHUB_OUTPUT
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          echo "sync_needed=false" >> $GITHUB_OUTPUT
 | 
					 | 
				
			||||||
        fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: sync v4
 | 
					 | 
				
			||||||
      if: steps.check_v4.outputs.sync_needed == 'true'
 | 
					 | 
				
			||||||
      run: |
 | 
					 | 
				
			||||||
        git clone --filter=blob:none --filter=tree:0 --branch v4 --single-branch ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY} repo
 | 
					 | 
				
			||||||
        cd repo
 | 
					 | 
				
			||||||
        git remote add --no-tags --fetch --track v4 upstream https://github.com/${GITHUB_REPOSITORY}
 | 
					 | 
				
			||||||
        git pull --rebase upstream v4
 | 
					 | 
				
			||||||
        git push upstream v4 --progress
 | 
					 | 
				
			||||||
        git push origin v4 --progress
 | 
					 | 
				
			||||||
        cd ../
 | 
					 | 
				
			||||||
        rm -rf repo
 | 
					 | 
				
			||||||
							
								
								
									
										39
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								README.md
									
									
									
									
									
								
							@@ -1,8 +1,8 @@
 | 
				
			|||||||
# HTTP Client
 | 
					# HTTP Client
 | 
				
			||||||

 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This plugin is an HTTP client for [Micro](https://pkg.go.dev/go.unistack.org/micro/v4).
 | 
					This plugin is an HTTP client for [Micro](https://pkg.go.dev/go.unistack.org/micro/v3).
 | 
				
			||||||
It implements the [micro.Client](https://pkg.go.dev/go.unistack.org/micro/v4/client#Client) interface.
 | 
					It implements the [micro.Client](https://pkg.go.dev/go.unistack.org/micro/v3/client#Client) interface.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Overview
 | 
					## Overview
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -13,13 +13,14 @@ implements HTTP rules defined in the [google/api/http.proto](https://github.com/
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
* Streaming is not yet implemented.
 | 
					* Streaming is not yet implemented.
 | 
				
			||||||
* Only protobuf-generated messages are supported.
 | 
					* Only protobuf-generated messages are supported.
 | 
				
			||||||
 | 
					* In `micro/v3`, metadata is implemented as `map[string]string`, which works for most headers but not for multiple `Set-Cookie` headers. The HTTP specification forbids the use of commas in `Set-Cookie` headers; therefore, their values cannot be parsed reliably. In `micro/v4`, metadata uses `map[string][]string`, resolving this issue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Usage
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
    "go.unistack.org/micro/v4"
 | 
					    "go.unistack.org/micro/v3"
 | 
				
			||||||
    http "go.unistack.org/micro-client-http/v4"
 | 
					    http "go.unistack.org/micro-client-http/v3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
service := micro.NewService(
 | 
					service := micro.NewService(
 | 
				
			||||||
@@ -32,9 +33,9 @@ service := micro.NewService(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
    "go.unistack.org/micro/v4/client"
 | 
					    "go.unistack.org/micro/v3/client"
 | 
				
			||||||
    http "go.unistack.org/micro-client-http/v4"
 | 
					    http "go.unistack.org/micro-client-http/v3"
 | 
				
			||||||
    jsoncodec "go.unistack.org/micro-codec-json/v4"
 | 
					    jsoncodec "go.unistack.org/micro-codec-json/v3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
c := http.NewClient(
 | 
					c := http.NewClient(
 | 
				
			||||||
@@ -60,8 +61,8 @@ err := c.Call(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
    "go.unistack.org/micro/v4/client"
 | 
					    "go.unistack.org/micro/v3/client"
 | 
				
			||||||
    http "go.unistack.org/micro-client-http/v4"
 | 
					    http "go.unistack.org/micro-client-http/v3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err := c.Call(
 | 
					err := c.Call(
 | 
				
			||||||
@@ -79,8 +80,8 @@ err := c.Call(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
    "go.unistack.org/micro/v4/metadata"
 | 
					    "go.unistack.org/micro/v3/metadata"
 | 
				
			||||||
    http "go.unistack.org/micro-client-http/v4"
 | 
					    http "go.unistack.org/micro-client-http/v3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ctx := metadata.NewOutgoingContext(ctx, metadata.Pairs(
 | 
					ctx := metadata.NewOutgoingContext(ctx, metadata.Pairs(
 | 
				
			||||||
@@ -100,8 +101,8 @@ err := c.Call(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
    "go.unistack.org/micro/v4/metadata"
 | 
					    "go.unistack.org/micro/v3/metadata"
 | 
				
			||||||
    http "go.unistack.org/micro-client-http/v4"
 | 
					    http "go.unistack.org/micro-client-http/v3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
respMetadata := metadata.Metadata{}
 | 
					respMetadata := metadata.Metadata{}
 | 
				
			||||||
@@ -118,8 +119,8 @@ err := c.Call(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
    "go.unistack.org/micro/v4/metadata"
 | 
					    "go.unistack.org/micro/v3/metadata"
 | 
				
			||||||
    http "go.unistack.org/micro-client-http/v4"
 | 
					    http "go.unistack.org/micro-client-http/v3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(
 | 
					ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs(
 | 
				
			||||||
@@ -138,9 +139,9 @@ err := c.Call(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
```go
 | 
					```go
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
    http "go.unistack.org/micro-client-http/v4"
 | 
					    http "go.unistack.org/micro-client-http/v3"
 | 
				
			||||||
    status "go.unistack.org/micro-client-http/v4/status"
 | 
					    status "go.unistack.org/micro-client-http/v3/status"
 | 
				
			||||||
    jsoncodec "go.unistack.org/micro-codec-json/v4"
 | 
					    jsoncodec "go.unistack.org/micro-codec-json/v3"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err := c.Call(
 | 
					err := c.Call(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3745,7 +3745,7 @@ const file_test_messages_proto_rawDesc = "" +
 | 
				
			|||||||
	"\fSpecialError\x12\x12\n" +
 | 
						"\fSpecialError\x12\x12\n" +
 | 
				
			||||||
	"\x04code\x18\x01 \x01(\tR\x04code\x12\x10\n" +
 | 
						"\x04code\x18\x01 \x01(\tR\x04code\x12\x10\n" +
 | 
				
			||||||
	"\x03msg\x18\x02 \x01(\tR\x03msg\x12\x18\n" +
 | 
						"\x03msg\x18\x02 \x01(\tR\x03msg\x12\x18\n" +
 | 
				
			||||||
	"\awarning\x18\x03 \x01(\tR\awarningB2Z0go.unistack.org/micro-client-http/v4/proto;protob\x06proto3"
 | 
						"\awarning\x18\x03 \x01(\tR\awarningB2Z0go.unistack.org/micro-client-http/v3/proto;protob\x06proto3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	file_test_messages_proto_rawDescOnce sync.Once
 | 
						file_test_messages_proto_rawDescOnce sync.Once
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ syntax = "proto3";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package proto;
 | 
					package proto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
option go_package = "go.unistack.org/micro-client-http/v4/proto;proto";
 | 
					option go_package = "go.unistack.org/micro-client-http/v3/proto;proto";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message TestRequestBuilder {}
 | 
					message TestRequestBuilder {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"google.golang.org/protobuf/proto"
 | 
						"google.golang.org/protobuf/proto"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pb "go.unistack.org/micro-client-http/v4/builder/proto"
 | 
						pb "go.unistack.org/micro-client-http/v3/builder/proto"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// sink prevents the compiler from optimizing away parsePathTemplate results.
 | 
					// sink prevents the compiler from optimizing away parsePathTemplate results.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,8 @@ import (
 | 
				
			|||||||
	"github.com/stretchr/testify/require"
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
	"google.golang.org/protobuf/proto"
 | 
						"google.golang.org/protobuf/proto"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro-client-http/v4/builder"
 | 
						"go.unistack.org/micro-client-http/v3/builder"
 | 
				
			||||||
	pb "go.unistack.org/micro-client-http/v4/builder/proto"
 | 
						pb "go.unistack.org/micro-client-http/v3/builder/proto"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewRequestBuilder(t *testing.T) {
 | 
					func TestNewRequestBuilder(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										52
									
								
								client.go
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								client.go
									
									
									
									
									
								
							@@ -7,13 +7,13 @@ import (
 | 
				
			|||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v4/client"
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
	"go.unistack.org/micro/v4/errors"
 | 
						"go.unistack.org/micro/v3/errors"
 | 
				
			||||||
	"go.unistack.org/micro/v4/options"
 | 
						"go.unistack.org/micro/v3/options"
 | 
				
			||||||
	"go.unistack.org/micro/v4/semconv"
 | 
						"go.unistack.org/micro/v3/semconv"
 | 
				
			||||||
	"go.unistack.org/micro/v4/tracer"
 | 
						"go.unistack.org/micro/v3/tracer"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro-client-http/v4/status"
 | 
						"go.unistack.org/micro-client-http/v3/status"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ client.Client = (*Client)(nil)
 | 
					var _ client.Client = (*Client)(nil)
 | 
				
			||||||
@@ -21,11 +21,13 @@ var _ client.Client = (*Client)(nil)
 | 
				
			|||||||
var DefaultContentType = "application/json"
 | 
					var DefaultContentType = "application/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Client struct {
 | 
					type Client struct {
 | 
				
			||||||
	funcCall   client.FuncCall
 | 
						funcPublish      client.FuncPublish
 | 
				
			||||||
	funcStream client.FuncStream
 | 
						funcBatchPublish client.FuncBatchPublish
 | 
				
			||||||
	httpClient *http.Client
 | 
						funcCall         client.FuncCall
 | 
				
			||||||
	opts       client.Options
 | 
						funcStream       client.FuncStream
 | 
				
			||||||
	mu         sync.RWMutex
 | 
						httpClient       *http.Client
 | 
				
			||||||
 | 
						opts             client.Options
 | 
				
			||||||
 | 
						mu               sync.RWMutex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewClient(opts ...client.Option) *Client {
 | 
					func NewClient(opts ...client.Option) *Client {
 | 
				
			||||||
@@ -47,6 +49,8 @@ func NewClient(opts ...client.Option) *Client {
 | 
				
			|||||||
		c.httpClient = defaultHTTPClient(dialer, clientOpts.TLSConfig)
 | 
							c.httpClient = defaultHTTPClient(dialer, clientOpts.TLSConfig)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.funcPublish = c.fnPublish
 | 
				
			||||||
 | 
						c.funcBatchPublish = c.fnBatchPublish
 | 
				
			||||||
	c.funcCall = c.fnCall
 | 
						c.funcCall = c.fnCall
 | 
				
			||||||
	c.funcStream = c.fnStream
 | 
						c.funcStream = c.fnStream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -68,6 +72,10 @@ func (c *Client) Init(opts ...client.Option) error {
 | 
				
			|||||||
			c.funcCall = h(c.funcCall)
 | 
								c.funcCall = h(c.funcCall)
 | 
				
			||||||
		case client.HookStream:
 | 
							case client.HookStream:
 | 
				
			||||||
			c.funcStream = h(c.funcStream)
 | 
								c.funcStream = h(c.funcStream)
 | 
				
			||||||
 | 
							case client.HookPublish:
 | 
				
			||||||
 | 
								c.funcPublish = h(c.funcPublish)
 | 
				
			||||||
 | 
							case client.HookBatchPublish:
 | 
				
			||||||
 | 
								c.funcBatchPublish = h(c.funcBatchPublish)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -78,6 +86,20 @@ func (c *Client) Options() client.Options {
 | 
				
			|||||||
	return c.opts
 | 
						return c.opts
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) NewMessage(topic string, msg interface{}, opts ...client.MessageOption) client.Message {
 | 
				
			||||||
 | 
						msgOpts := client.NewMessageOptions(opts...)
 | 
				
			||||||
 | 
						if msgOpts.ContentType == "" {
 | 
				
			||||||
 | 
							msgOpts.ContentType = c.opts.ContentType
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &httpMessage{
 | 
				
			||||||
 | 
							topic:   topic,
 | 
				
			||||||
 | 
							payload: msg,
 | 
				
			||||||
 | 
							opts:    msgOpts,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Client) NewRequest(service, method string, req any, opts ...client.RequestOption) client.Request {
 | 
					func (c *Client) NewRequest(service, method string, req any, opts ...client.RequestOption) client.Request {
 | 
				
			||||||
	reqOpts := client.NewRequestOptions(opts...)
 | 
						reqOpts := client.NewRequestOptions(opts...)
 | 
				
			||||||
	if reqOpts.ContentType == "" {
 | 
						if reqOpts.ContentType == "" {
 | 
				
			||||||
@@ -141,6 +163,14 @@ func (c *Client) Stream(ctx context.Context, req client.Request, opts ...client.
 | 
				
			|||||||
	return c.funcStream(ctx, req, opts...)
 | 
						return c.funcStream(ctx, req, opts...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) Publish(ctx context.Context, p client.Message, opts ...client.PublishOption) error {
 | 
				
			||||||
 | 
						return c.funcPublish(ctx, p, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) BatchPublish(ctx context.Context, ps []client.Message, opts ...client.PublishOption) error {
 | 
				
			||||||
 | 
						return c.funcBatchPublish(ctx, ps, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Client) String() string {
 | 
					func (c *Client) String() string {
 | 
				
			||||||
	return "http"
 | 
						return "http"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,14 +11,14 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v4/client"
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
	"go.unistack.org/micro/v4/codec"
 | 
						"go.unistack.org/micro/v3/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v4/logger"
 | 
						"go.unistack.org/micro/v3/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v4/metadata"
 | 
						"go.unistack.org/micro/v3/metadata"
 | 
				
			||||||
	"google.golang.org/protobuf/proto"
 | 
						"google.golang.org/protobuf/proto"
 | 
				
			||||||
	"google.golang.org/protobuf/reflect/protoreflect"
 | 
						"google.golang.org/protobuf/reflect/protoreflect"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro-client-http/v4/builder"
 | 
						"go.unistack.org/micro-client-http/v3/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func buildHTTPRequest(
 | 
					func buildHTTPRequest(
 | 
				
			||||||
@@ -218,7 +218,7 @@ func setHeadersAndCookies(ctx context.Context, r *http.Request, ct string, opts
 | 
				
			|||||||
				applyCookies(r, v)
 | 
									applyCookies(r, v)
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			r.Header[k] = append(r.Header[k], v...)
 | 
								r.Header[k] = append(r.Header[k], v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -228,20 +228,18 @@ func setHeadersAndCookies(ctx context.Context, r *http.Request, ct string, opts
 | 
				
			|||||||
				applyCookies(r, v)
 | 
									applyCookies(r, v)
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			r.Header[k] = append(r.Header[k], v...)
 | 
								r.Header[k] = append(r.Header[k], v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func applyCookies(r *http.Request, rawCookies []string) {
 | 
					func applyCookies(r *http.Request, rawCookies string) {
 | 
				
			||||||
	if len(rawCookies) == 0 {
 | 
						if len(rawCookies) == 0 {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tmp := http.Request{Header: http.Header{}}
 | 
						tmp := http.Request{Header: http.Header{}}
 | 
				
			||||||
	for _, raw := range rawCookies {
 | 
						tmp.Header.Set("Cookie", rawCookies)
 | 
				
			||||||
		tmp.Header.Add("Cookie", raw)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, c := range tmp.Cookies() {
 | 
						for _, c := range tmp.Cookies() {
 | 
				
			||||||
		r.AddCookie(c)
 | 
							r.AddCookie(c)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,10 +6,10 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/require"
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
	jsoncodec "go.unistack.org/micro-codec-json/v4"
 | 
						jsoncodec "go.unistack.org/micro-codec-json/v3"
 | 
				
			||||||
	"google.golang.org/protobuf/proto"
 | 
						"google.golang.org/protobuf/proto"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pb "go.unistack.org/micro-client-http/v4/builder/proto"
 | 
						pb "go.unistack.org/micro-client-http/v3/builder/proto"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestJoinURL(t *testing.T) {
 | 
					func TestJoinURL(t *testing.T) {
 | 
				
			||||||
@@ -232,24 +232,24 @@ func TestMarshallMsg(t *testing.T) {
 | 
				
			|||||||
func TestApplyCookies(t *testing.T) {
 | 
					func TestApplyCookies(t *testing.T) {
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		name       string
 | 
							name       string
 | 
				
			||||||
		rawCookies []string
 | 
							rawCookies string
 | 
				
			||||||
		want       []*http.Cookie
 | 
							want       []*http.Cookie
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:       "empty",
 | 
								name:       "empty",
 | 
				
			||||||
			rawCookies: []string{},
 | 
								rawCookies: "",
 | 
				
			||||||
			want:       []*http.Cookie{},
 | 
								want:       []*http.Cookie{},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:       "single cookie",
 | 
								name:       "single cookie",
 | 
				
			||||||
			rawCookies: []string{"session=abc123"},
 | 
								rawCookies: "session=abc123",
 | 
				
			||||||
			want: []*http.Cookie{
 | 
								want: []*http.Cookie{
 | 
				
			||||||
				{Name: "session", Value: "abc123"},
 | 
									{Name: "session", Value: "abc123"},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:       "multiple cookies separate items",
 | 
								name:       "multiple cookies separate items",
 | 
				
			||||||
			rawCookies: []string{"session=abc123", "user=john"},
 | 
								rawCookies: "session=abc123; user=john",
 | 
				
			||||||
			want: []*http.Cookie{
 | 
								want: []*http.Cookie{
 | 
				
			||||||
				{Name: "session", Value: "abc123"},
 | 
									{Name: "session", Value: "abc123"},
 | 
				
			||||||
				{Name: "user", Value: "john"},
 | 
									{Name: "user", Value: "john"},
 | 
				
			||||||
@@ -257,7 +257,7 @@ func TestApplyCookies(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:       "multiple cookies in one item",
 | 
								name:       "multiple cookies in one item",
 | 
				
			||||||
			rawCookies: []string{"a=1; b=2"},
 | 
								rawCookies: "a=1; b=2",
 | 
				
			||||||
			want: []*http.Cookie{
 | 
								want: []*http.Cookie{
 | 
				
			||||||
				{Name: "a", Value: "1"},
 | 
									{Name: "a", Value: "1"},
 | 
				
			||||||
				{Name: "b", Value: "2"},
 | 
									{Name: "b", Value: "2"},
 | 
				
			||||||
@@ -265,7 +265,7 @@ func TestApplyCookies(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:       "mix of combined and separate cookies",
 | 
								name:       "mix of combined and separate cookies",
 | 
				
			||||||
			rawCookies: []string{"a=1; b=2", "c=3"},
 | 
								rawCookies: "a=1; b=2; c=3",
 | 
				
			||||||
			want: []*http.Cookie{
 | 
								want: []*http.Cookie{
 | 
				
			||||||
				{Name: "a", Value: "1"},
 | 
									{Name: "a", Value: "1"},
 | 
				
			||||||
				{Name: "b", Value: "2"},
 | 
									{Name: "b", Value: "2"},
 | 
				
			||||||
@@ -274,7 +274,7 @@ func TestApplyCookies(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:       "duplicate cookies",
 | 
								name:       "duplicate cookies",
 | 
				
			||||||
			rawCookies: []string{"session=abc123", "session=xyz"},
 | 
								rawCookies: "session=abc123; session=xyz",
 | 
				
			||||||
			want: []*http.Cookie{
 | 
								want: []*http.Cookie{
 | 
				
			||||||
				{Name: "session", Value: "abc123"},
 | 
									{Name: "session", Value: "abc123"},
 | 
				
			||||||
				{Name: "session", Value: "xyz"},
 | 
									{Name: "session", Value: "xyz"},
 | 
				
			||||||
@@ -282,7 +282,7 @@ func TestApplyCookies(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name:       "cookie with spaces",
 | 
								name:       "cookie with spaces",
 | 
				
			||||||
			rawCookies: []string{"token=abc 123"},
 | 
								rawCookies: "token=abc 123",
 | 
				
			||||||
			want: []*http.Cookie{
 | 
								want: []*http.Cookie{
 | 
				
			||||||
				{Name: "token", Value: "abc 123", Quoted: true},
 | 
									{Name: "token", Value: "abc 123", Quoted: true},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										84
									
								
								client_publish.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								client_publish.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					package http
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v3/broker"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v3/codec"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v3/errors"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v3/metadata"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) publish(ctx context.Context, ps []client.Message, opts ...client.PublishOption) error {
 | 
				
			||||||
 | 
						var body []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						options := client.NewPublishOptions(opts...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// get proxy
 | 
				
			||||||
 | 
						exchange := ""
 | 
				
			||||||
 | 
						if v, ok := os.LookupEnv("MICRO_PROXY"); ok {
 | 
				
			||||||
 | 
							exchange = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// get the exchange
 | 
				
			||||||
 | 
						if len(options.Exchange) > 0 {
 | 
				
			||||||
 | 
							exchange = options.Exchange
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						msgs := make([]*broker.Message, 0, len(ps))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						omd, ok := metadata.FromOutgoingContext(ctx)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							omd = metadata.New(2)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, p := range ps {
 | 
				
			||||||
 | 
							md := metadata.Copy(omd)
 | 
				
			||||||
 | 
							topic := p.Topic()
 | 
				
			||||||
 | 
							if len(exchange) > 0 {
 | 
				
			||||||
 | 
								topic = exchange
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							md.Set(metadata.HeaderTopic, topic)
 | 
				
			||||||
 | 
							iter := p.Metadata().Iterator()
 | 
				
			||||||
 | 
							var k, v string
 | 
				
			||||||
 | 
							for iter.Next(&k, &v) {
 | 
				
			||||||
 | 
								md.Set(k, v)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							md[metadata.HeaderContentType] = p.ContentType()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// passed in raw data
 | 
				
			||||||
 | 
							if d, ok := p.Payload().(*codec.Frame); ok {
 | 
				
			||||||
 | 
								body = d.Data
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// use codec for payload
 | 
				
			||||||
 | 
								cf, err := c.newCodec(p.ContentType())
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return errors.InternalServerError("go.micro.client", "%+v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// set the body
 | 
				
			||||||
 | 
								b, err := cf.Marshal(p.Payload())
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return errors.InternalServerError("go.micro.client", "%+v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								body = b
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							msgs = append(msgs, &broker.Message{Header: md, Body: body})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c.opts.Broker.BatchPublish(
 | 
				
			||||||
 | 
							ctx,
 | 
				
			||||||
 | 
							msgs,
 | 
				
			||||||
 | 
							broker.PublishContext(options.Context),
 | 
				
			||||||
 | 
							broker.PublishBodyOnly(options.BodyOnly),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) fnPublish(ctx context.Context, p client.Message, opts ...client.PublishOption) error {
 | 
				
			||||||
 | 
						return c.publish(ctx, []client.Message{p}, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Client) fnBatchPublish(ctx context.Context, ps []client.Message, opts ...client.PublishOption) error {
 | 
				
			||||||
 | 
						return c.publish(ctx, ps, opts...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -3,7 +3,7 @@ package http
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v4/client"
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Add stream support in the future.
 | 
					// TODO: Add stream support in the future.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,14 +10,14 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v4/client"
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
	"go.unistack.org/micro/v4/codec"
 | 
						"go.unistack.org/micro/v3/codec"
 | 
				
			||||||
	"go.unistack.org/micro/v4/errors"
 | 
						"go.unistack.org/micro/v3/errors"
 | 
				
			||||||
	"go.unistack.org/micro/v4/logger"
 | 
						"go.unistack.org/micro/v3/logger"
 | 
				
			||||||
	"go.unistack.org/micro/v4/metadata"
 | 
						"go.unistack.org/micro/v3/metadata"
 | 
				
			||||||
	"go.unistack.org/micro/v4/selector"
 | 
						"go.unistack.org/micro/v3/selector"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro-client-http/v4/status"
 | 
						"go.unistack.org/micro-client-http/v3/status"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Client) fnCall(ctx context.Context, req client.Request, rsp any, opts ...client.CallOption) error {
 | 
					func (c *Client) fnCall(ctx context.Context, req client.Request, rsp any, opts ...client.CallOption) error {
 | 
				
			||||||
@@ -209,7 +209,7 @@ func (c *Client) parseRsp(ctx context.Context, hrsp *http.Response, rsp any, opt
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if opts.ResponseMetadata != nil {
 | 
						if opts.ResponseMetadata != nil {
 | 
				
			||||||
		for k, v := range hrsp.Header {
 | 
							for k, v := range hrsp.Header {
 | 
				
			||||||
			opts.ResponseMetadata.Append(k, v...)
 | 
								opts.ResponseMetadata.Set(k, strings.Join(v, ","))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,15 +9,15 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/require"
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
	jsoncodec "go.unistack.org/micro-codec-json/v4"
 | 
						jsoncodec "go.unistack.org/micro-codec-json/v3"
 | 
				
			||||||
	"go.unistack.org/micro/v4/client"
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
	microerr "go.unistack.org/micro/v4/errors"
 | 
						microerr "go.unistack.org/micro/v3/errors"
 | 
				
			||||||
	"go.unistack.org/micro/v4/metadata"
 | 
						"go.unistack.org/micro/v3/metadata"
 | 
				
			||||||
	"google.golang.org/protobuf/proto"
 | 
						"google.golang.org/protobuf/proto"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	httpcli "go.unistack.org/micro-client-http/v4"
 | 
						httpcli "go.unistack.org/micro-client-http/v3"
 | 
				
			||||||
	pb "go.unistack.org/micro-client-http/v4/builder/proto"
 | 
						pb "go.unistack.org/micro-client-http/v3/builder/proto"
 | 
				
			||||||
	"go.unistack.org/micro-client-http/v4/status"
 | 
						"go.unistack.org/micro-client-http/v3/status"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestClient_Call_Get(t *testing.T) {
 | 
					func TestClient_Call_Get(t *testing.T) {
 | 
				
			||||||
@@ -130,9 +130,10 @@ func TestClient_Call_Get(t *testing.T) {
 | 
				
			|||||||
			)
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var (
 | 
								var (
 | 
				
			||||||
				ctx = metadata.NewOutgoingContext(
 | 
									md, _ = metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
				
			||||||
 | 
									ctx   = metadata.NewOutgoingContext(
 | 
				
			||||||
					context.Background(),
 | 
										context.Background(),
 | 
				
			||||||
					metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value"),
 | 
										md,
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
				rsp          = &response{}
 | 
									rsp          = &response{}
 | 
				
			||||||
				respMetadata = metadata.Metadata{}
 | 
									respMetadata = metadata.Metadata{}
 | 
				
			||||||
@@ -162,8 +163,8 @@ func TestClient_Call_Get(t *testing.T) {
 | 
				
			|||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				require.NoError(t, err)
 | 
									require.NoError(t, err)
 | 
				
			||||||
				require.True(t, proto.Equal(tt.wantRsp, rsp))
 | 
									require.True(t, proto.Equal(tt.wantRsp, rsp))
 | 
				
			||||||
				require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
									require.Equal(t, "application/json", respMetadata.MustGet("Content-Type"))
 | 
				
			||||||
				require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
									require.Equal(t, "My-Header-Value", respMetadata.MustGet("My-Header"))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -278,9 +279,10 @@ func TestClient_Call_Head(t *testing.T) {
 | 
				
			|||||||
			)
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var (
 | 
								var (
 | 
				
			||||||
				ctx = metadata.NewOutgoingContext(
 | 
									md, _ = metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
				
			||||||
 | 
									ctx   = metadata.NewOutgoingContext(
 | 
				
			||||||
					context.Background(),
 | 
										context.Background(),
 | 
				
			||||||
					metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value"),
 | 
										md,
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
				rsp          = &response{}
 | 
									rsp          = &response{}
 | 
				
			||||||
				respMetadata = metadata.Metadata{}
 | 
									respMetadata = metadata.Metadata{}
 | 
				
			||||||
@@ -310,8 +312,8 @@ func TestClient_Call_Head(t *testing.T) {
 | 
				
			|||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				require.NoError(t, err)
 | 
									require.NoError(t, err)
 | 
				
			||||||
				require.True(t, proto.Equal(tt.wantRsp, rsp))
 | 
									require.True(t, proto.Equal(tt.wantRsp, rsp))
 | 
				
			||||||
				require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
									require.Equal(t, "application/json", respMetadata.MustGet("Content-Type"))
 | 
				
			||||||
				require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
									require.Equal(t, "My-Header-Value", respMetadata.MustGet("My-Header"))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -462,9 +464,10 @@ func TestClient_Call_Post(t *testing.T) {
 | 
				
			|||||||
			)
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var (
 | 
								var (
 | 
				
			||||||
				ctx = metadata.NewOutgoingContext(
 | 
									md, _ = metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
				
			||||||
 | 
									ctx   = metadata.NewOutgoingContext(
 | 
				
			||||||
					context.Background(),
 | 
										context.Background(),
 | 
				
			||||||
					metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value"),
 | 
										md,
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
				rsp          = &response{}
 | 
									rsp          = &response{}
 | 
				
			||||||
				respMetadata = metadata.Metadata{}
 | 
									respMetadata = metadata.Metadata{}
 | 
				
			||||||
@@ -494,8 +497,8 @@ func TestClient_Call_Post(t *testing.T) {
 | 
				
			|||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				require.NoError(t, err)
 | 
									require.NoError(t, err)
 | 
				
			||||||
				require.True(t, proto.Equal(tt.wantRsp, rsp))
 | 
									require.True(t, proto.Equal(tt.wantRsp, rsp))
 | 
				
			||||||
				require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
									require.Equal(t, "application/json", respMetadata.MustGet("Content-Type"))
 | 
				
			||||||
				require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
									require.Equal(t, "My-Header-Value", respMetadata.MustGet("My-Header"))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -611,9 +614,10 @@ func TestClient_Call_Delete(t *testing.T) {
 | 
				
			|||||||
			)
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var (
 | 
								var (
 | 
				
			||||||
				ctx = metadata.NewOutgoingContext(
 | 
									md, _ = metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
				
			||||||
 | 
									ctx   = metadata.NewOutgoingContext(
 | 
				
			||||||
					context.Background(),
 | 
										context.Background(),
 | 
				
			||||||
					metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value"),
 | 
										md,
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
				rsp          = &response{}
 | 
									rsp          = &response{}
 | 
				
			||||||
				respMetadata = metadata.Metadata{}
 | 
									respMetadata = metadata.Metadata{}
 | 
				
			||||||
@@ -643,8 +647,8 @@ func TestClient_Call_Delete(t *testing.T) {
 | 
				
			|||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				require.NoError(t, err)
 | 
									require.NoError(t, err)
 | 
				
			||||||
				require.True(t, proto.Equal(tt.wantRsp, rsp))
 | 
									require.True(t, proto.Equal(tt.wantRsp, rsp))
 | 
				
			||||||
				require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
									require.Equal(t, "application/json", respMetadata.MustGet("Content-Type"))
 | 
				
			||||||
				require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
									require.Equal(t, "My-Header-Value", respMetadata.MustGet("My-Header"))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -767,9 +771,10 @@ func TestClient_Call_APIError_WithErrorsMap(t *testing.T) {
 | 
				
			|||||||
			)
 | 
								)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			var (
 | 
								var (
 | 
				
			||||||
				ctx = metadata.NewOutgoingContext(
 | 
									md, _ = metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
				
			||||||
 | 
									ctx   = metadata.NewOutgoingContext(
 | 
				
			||||||
					context.Background(),
 | 
										context.Background(),
 | 
				
			||||||
					metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value"),
 | 
										md,
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
				req = &request{UserId: "123", OrderId: 456}
 | 
									req = &request{UserId: "123", OrderId: 456}
 | 
				
			||||||
				rsp = &response{}
 | 
									rsp = &response{}
 | 
				
			||||||
@@ -803,8 +808,8 @@ func TestClient_Call_APIError_WithErrorsMap(t *testing.T) {
 | 
				
			|||||||
			require.Equal(t, tt.expectedStatus, s)
 | 
								require.Equal(t, tt.expectedStatus, s)
 | 
				
			||||||
			require.Empty(t, rsp)
 | 
								require.Empty(t, rsp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
								require.Equal(t, "application/json", respMetadata.MustGet("Content-Type"))
 | 
				
			||||||
			require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
								require.Equal(t, "My-Header-Value", respMetadata.MustGet("My-Header"))
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -858,9 +863,10 @@ func TestClient_Call_APIError_WithoutErrorsMap(t *testing.T) {
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		ctx = metadata.NewOutgoingContext(
 | 
							md, _ = metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
				
			||||||
 | 
							ctx   = metadata.NewOutgoingContext(
 | 
				
			||||||
			context.Background(),
 | 
								context.Background(),
 | 
				
			||||||
			metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value"),
 | 
								md,
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
		req = &request{UserId: "123", OrderId: 456}
 | 
							req = &request{UserId: "123", OrderId: 456}
 | 
				
			||||||
		rsp = &response{}
 | 
							rsp = &response{}
 | 
				
			||||||
@@ -890,8 +896,8 @@ func TestClient_Call_APIError_WithoutErrorsMap(t *testing.T) {
 | 
				
			|||||||
	require.Equal(t, expectedStatus, s)
 | 
						require.Equal(t, expectedStatus, s)
 | 
				
			||||||
	require.Empty(t, rsp)
 | 
						require.Empty(t, rsp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
						require.Equal(t, "application/json", respMetadata.MustGet("Content-Type"))
 | 
				
			||||||
	require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
						require.Equal(t, "My-Header-Value", respMetadata.MustGet("My-Header"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestClient_Call_HeadersAndCookies(t *testing.T) {
 | 
					func TestClient_Call_HeadersAndCookies(t *testing.T) {
 | 
				
			||||||
@@ -948,7 +954,8 @@ func TestClient_Call_HeadersAndCookies(t *testing.T) {
 | 
				
			|||||||
				}))
 | 
									}))
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			prepareMetadata: func() metadata.Metadata {
 | 
								prepareMetadata: func() metadata.Metadata {
 | 
				
			||||||
				return metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
									md, _ := metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
				
			||||||
 | 
									return md
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			headerOption: httpcli.Header("Authorization", "true", "My-Header", "true"),
 | 
								headerOption: httpcli.Header("Authorization", "true", "My-Header", "true"),
 | 
				
			||||||
			expectedRsp:  &response{Id: "product-id", Name: "product-name"},
 | 
								expectedRsp:  &response{Id: "product-id", Name: "product-name"},
 | 
				
			||||||
@@ -992,7 +999,8 @@ func TestClient_Call_HeadersAndCookies(t *testing.T) {
 | 
				
			|||||||
				}))
 | 
									}))
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			prepareMetadata: func() metadata.Metadata {
 | 
								prepareMetadata: func() metadata.Metadata {
 | 
				
			||||||
				return metadata.Pairs("Authorization", "Bearer token")
 | 
									md, _ := metadata.Pairs("Authorization", "Bearer token")
 | 
				
			||||||
 | 
									return md
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			headerOption: httpcli.Header("Authorization", "true", "My-Header", "true"),
 | 
								headerOption: httpcli.Header("Authorization", "true", "My-Header", "true"),
 | 
				
			||||||
			wantErr:      true,
 | 
								wantErr:      true,
 | 
				
			||||||
@@ -1035,7 +1043,8 @@ func TestClient_Call_HeadersAndCookies(t *testing.T) {
 | 
				
			|||||||
				}))
 | 
									}))
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			prepareMetadata: func() metadata.Metadata {
 | 
								prepareMetadata: func() metadata.Metadata {
 | 
				
			||||||
				return metadata.Pairs("Cookie", "session_id=abc123; theme=dark")
 | 
									md, _ := metadata.Pairs("Cookie", "session_id=abc123; theme=dark")
 | 
				
			||||||
 | 
									return md
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			cookieOption: httpcli.Cookie("session_id", "true", "theme", "true"),
 | 
								cookieOption: httpcli.Cookie("session_id", "true", "theme", "true"),
 | 
				
			||||||
			expectedRsp:  &response{Id: "product-id", Name: "product-name"},
 | 
								expectedRsp:  &response{Id: "product-id", Name: "product-name"},
 | 
				
			||||||
@@ -1078,7 +1087,8 @@ func TestClient_Call_HeadersAndCookies(t *testing.T) {
 | 
				
			|||||||
				}))
 | 
									}))
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			prepareMetadata: func() metadata.Metadata {
 | 
								prepareMetadata: func() metadata.Metadata {
 | 
				
			||||||
				return metadata.Pairs("Cookie", "session_id=abc123")
 | 
									md, _ := metadata.Pairs("Cookie", "session_id=abc123")
 | 
				
			||||||
 | 
									return md
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			cookieOption: httpcli.Cookie("session_id", "true", "theme", "true"),
 | 
								cookieOption: httpcli.Cookie("session_id", "true", "theme", "true"),
 | 
				
			||||||
			wantErr:      true,
 | 
								wantErr:      true,
 | 
				
			||||||
@@ -1123,11 +1133,12 @@ func TestClient_Call_HeadersAndCookies(t *testing.T) {
 | 
				
			|||||||
				}))
 | 
									}))
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			prepareMetadata: func() metadata.Metadata {
 | 
								prepareMetadata: func() metadata.Metadata {
 | 
				
			||||||
				return metadata.Pairs(
 | 
									md, _ := metadata.Pairs(
 | 
				
			||||||
					"Authorization", "Bearer token",
 | 
										"Authorization", "Bearer token",
 | 
				
			||||||
					"My-Header", "My-Header-Value",
 | 
										"My-Header", "My-Header-Value",
 | 
				
			||||||
					"Cookie", "session_id=abc123; theme=dark",
 | 
										"Cookie", "session_id=abc123; theme=dark",
 | 
				
			||||||
				)
 | 
									)
 | 
				
			||||||
 | 
									return md
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			headerOption: httpcli.Header("Authorization", "true", "My-Header", "true"),
 | 
								headerOption: httpcli.Header("Authorization", "true", "My-Header", "true"),
 | 
				
			||||||
			cookieOption: httpcli.Cookie("session_id", "true", "theme", "true"),
 | 
								cookieOption: httpcli.Cookie("session_id", "true", "theme", "true"),
 | 
				
			||||||
@@ -1179,105 +1190,13 @@ func TestClient_Call_HeadersAndCookies(t *testing.T) {
 | 
				
			|||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				require.NoError(t, err)
 | 
									require.NoError(t, err)
 | 
				
			||||||
				require.True(t, proto.Equal(tt.expectedRsp, rsp))
 | 
									require.True(t, proto.Equal(tt.expectedRsp, rsp))
 | 
				
			||||||
				require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
									require.Equal(t, "application/json", respMetadata.MustGet("Content-Type"))
 | 
				
			||||||
				require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
									require.Equal(t, "My-Header-Value", respMetadata.MustGet("My-Header"))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestClient_Call_SetCookie(t *testing.T) {
 | 
					 | 
				
			||||||
	type (
 | 
					 | 
				
			||||||
		request  = pb.Test_Client_Call_Request
 | 
					 | 
				
			||||||
		response = pb.Test_Client_Call_Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	serverMock := func() *httptest.Server {
 | 
					 | 
				
			||||||
		return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
					 | 
				
			||||||
			// Validate request
 | 
					 | 
				
			||||||
			require.Equal(t, "POST", r.Method)
 | 
					 | 
				
			||||||
			require.Equal(t, "/user/products", r.URL.RequestURI())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			require.Equal(t, "application/json", r.Header.Get("Content-Type"))
 | 
					 | 
				
			||||||
			require.Equal(t, "Bearer token", r.Header.Get("Authorization"))
 | 
					 | 
				
			||||||
			require.Equal(t, "My-Header-Value", r.Header.Get("My-Header"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			buf, err := io.ReadAll(r.Body)
 | 
					 | 
				
			||||||
			require.NoError(t, err)
 | 
					 | 
				
			||||||
			defer r.Body.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			c := jsoncodec.NewCodec()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			req := &request{}
 | 
					 | 
				
			||||||
			err = c.Unmarshal(buf, req)
 | 
					 | 
				
			||||||
			require.NoError(t, err)
 | 
					 | 
				
			||||||
			require.True(t, proto.Equal(&request{UserId: "123", OrderId: 456}, req))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Return response
 | 
					 | 
				
			||||||
			cookieN1, err := http.ParseSetCookie("sessionid=abc123; Path=/; HttpOnly")
 | 
					 | 
				
			||||||
			require.NoError(t, err)
 | 
					 | 
				
			||||||
			http.SetCookie(w, cookieN1)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			cookieN2, err := http.ParseSetCookie("theme=dark; Path=/; Max-Age=3600")
 | 
					 | 
				
			||||||
			require.NoError(t, err)
 | 
					 | 
				
			||||||
			http.SetCookie(w, cookieN2)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			cookieN3, err := http.ParseSetCookie("lang=en-US; Path=/")
 | 
					 | 
				
			||||||
			require.NoError(t, err)
 | 
					 | 
				
			||||||
			http.SetCookie(w, cookieN3)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			w.Header().Set("Content-Type", "application/json")
 | 
					 | 
				
			||||||
			w.Header().Set("My-Header", "My-Header-Value")
 | 
					 | 
				
			||||||
			w.WriteHeader(http.StatusNoContent)
 | 
					 | 
				
			||||||
		}))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	server := serverMock()
 | 
					 | 
				
			||||||
	defer server.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	httpClient := httpcli.NewClient(
 | 
					 | 
				
			||||||
		client.Codec("application/json", jsoncodec.NewCodec()),
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		ctx = metadata.NewOutgoingContext(
 | 
					 | 
				
			||||||
			context.Background(),
 | 
					 | 
				
			||||||
			metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value"),
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
		req = &request{UserId: "123", OrderId: 456}
 | 
					 | 
				
			||||||
		rsp = &response{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		respMetadata = metadata.Metadata{}
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	opts := []client.CallOption{
 | 
					 | 
				
			||||||
		client.WithAddress(server.URL),
 | 
					 | 
				
			||||||
		client.WithResponseMetadata(&respMetadata),
 | 
					 | 
				
			||||||
		httpcli.Method(http.MethodPost),
 | 
					 | 
				
			||||||
		httpcli.Path("/user/products"),
 | 
					 | 
				
			||||||
		httpcli.Body("*"),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	expectedSetCookie := []string{"sessionid=abc123; Path=/; HttpOnly", "theme=dark; Path=/; Max-Age=3600", "lang=en-US; Path=/"}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err := httpClient.Call(
 | 
					 | 
				
			||||||
		ctx,
 | 
					 | 
				
			||||||
		httpClient.NewRequest("test.service", "Test.Call", req),
 | 
					 | 
				
			||||||
		rsp,
 | 
					 | 
				
			||||||
		opts...,
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	require.NoError(t, err)
 | 
					 | 
				
			||||||
	require.Empty(t, rsp)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
					 | 
				
			||||||
	require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
					 | 
				
			||||||
	for i, raw := range respMetadata.Get("Set-Cookie") {
 | 
					 | 
				
			||||||
		cookie, err := http.ParseSetCookie(raw)
 | 
					 | 
				
			||||||
		require.NoError(t, err)
 | 
					 | 
				
			||||||
		require.Equal(t, expectedSetCookie[i], cookie.String())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestClient_Call_NoContent(t *testing.T) {
 | 
					func TestClient_Call_NoContent(t *testing.T) {
 | 
				
			||||||
	type (
 | 
						type (
 | 
				
			||||||
		request  = pb.Test_Client_Call_Request
 | 
							request  = pb.Test_Client_Call_Request
 | 
				
			||||||
@@ -1320,9 +1239,10 @@ func TestClient_Call_NoContent(t *testing.T) {
 | 
				
			|||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		ctx = metadata.NewOutgoingContext(
 | 
							md, _ = metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value")
 | 
				
			||||||
 | 
							ctx   = metadata.NewOutgoingContext(
 | 
				
			||||||
			context.Background(),
 | 
								context.Background(),
 | 
				
			||||||
			metadata.Pairs("Authorization", "Bearer token", "My-Header", "My-Header-Value"),
 | 
								md,
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
		req = &request{UserId: "123", OrderId: 456}
 | 
							req = &request{UserId: "123", OrderId: 456}
 | 
				
			||||||
		rsp = &response{}
 | 
							rsp = &response{}
 | 
				
			||||||
@@ -1347,8 +1267,8 @@ func TestClient_Call_NoContent(t *testing.T) {
 | 
				
			|||||||
	require.NoError(t, err)
 | 
						require.NoError(t, err)
 | 
				
			||||||
	require.Empty(t, rsp)
 | 
						require.Empty(t, rsp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	require.Equal(t, "application/json", respMetadata.GetJoined("Content-Type"))
 | 
						require.Equal(t, "application/json", respMetadata.MustGet("Content-Type"))
 | 
				
			||||||
	require.Equal(t, "My-Header-Value", respMetadata.GetJoined("My-Header"))
 | 
						require.Equal(t, "My-Header-Value", respMetadata.MustGet("My-Header"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestClient_Call_RequestTimeoutError(t *testing.T) {
 | 
					func TestClient_Call_RequestTimeoutError(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								go.mod
									
									
									
									
									
								
							@@ -1,25 +1,26 @@
 | 
				
			|||||||
module go.unistack.org/micro-client-http/v4
 | 
					module go.unistack.org/micro-client-http/v3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.23.0
 | 
					go 1.24.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
toolchain go1.24.2
 | 
					toolchain go1.24.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/stretchr/testify v1.11.1
 | 
						github.com/stretchr/testify v1.11.1
 | 
				
			||||||
	go.unistack.org/micro-codec-json/v4 v4.1.0
 | 
						go.unistack.org/micro-codec-json/v3 v3.10.3
 | 
				
			||||||
	go.unistack.org/micro/v4 v4.1.19
 | 
						go.unistack.org/micro/v3 v3.11.48
 | 
				
			||||||
	google.golang.org/protobuf v1.36.9
 | 
						google.golang.org/protobuf v1.36.10
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
 | 
						github.com/ash3in/uuidv8 v1.2.0 // indirect
 | 
				
			||||||
	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 | 
						github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 | 
				
			||||||
	github.com/google/uuid v1.6.0 // indirect
 | 
						github.com/google/uuid v1.6.0 // indirect
 | 
				
			||||||
 | 
						github.com/kr/pretty v0.3.1 // indirect
 | 
				
			||||||
	github.com/matoous/go-nanoid v1.5.1 // indirect
 | 
						github.com/matoous/go-nanoid v1.5.1 // indirect
 | 
				
			||||||
	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 | 
						github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 | 
				
			||||||
	github.com/spf13/cast v1.9.2 // indirect
 | 
						go.unistack.org/micro-proto/v3 v3.4.1 // indirect
 | 
				
			||||||
	go.unistack.org/micro-proto/v4 v4.1.0 // indirect
 | 
						golang.org/x/sys v0.36.0 // indirect
 | 
				
			||||||
	golang.org/x/sys v0.35.0 // indirect
 | 
						google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect
 | 
				
			||||||
	google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect
 | 
						google.golang.org/grpc v1.75.1 // indirect
 | 
				
			||||||
	google.golang.org/grpc v1.75.0 // indirect
 | 
					 | 
				
			||||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
						gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								go.sum
									
									
									
									
									
								
							@@ -1,7 +1,10 @@
 | 
				
			|||||||
 | 
					github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
 | 
				
			||||||
 | 
					github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
 | 
				
			||||||
 | 
					github.com/ash3in/uuidv8 v1.2.0 h1:2oogGdtCPwaVtyvPPGin4TfZLtOGE5F+W++E880G6SI=
 | 
				
			||||||
 | 
					github.com/ash3in/uuidv8 v1.2.0/go.mod h1:BnU0wJBxnzdEKmVg4xckBkD+VZuecTFTUP3M0dWgyY4=
 | 
				
			||||||
 | 
					github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 | 
					github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
 | 
					 | 
				
			||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 | 
					 | 
				
			||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 | 
					github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 | 
				
			||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 | 
					github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 | 
				
			||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 | 
					github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 | 
				
			||||||
@@ -14,32 +17,32 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 | 
				
			|||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 | 
					github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 | 
				
			||||||
github.com/matoous/go-nanoid v1.5.1 h1:aCjdvTyO9LLnTIi0fgdXhOPPvOHjpXN6Ik9DaNjIct4=
 | 
					github.com/matoous/go-nanoid v1.5.1 h1:aCjdvTyO9LLnTIi0fgdXhOPPvOHjpXN6Ik9DaNjIct4=
 | 
				
			||||||
github.com/matoous/go-nanoid v1.5.1/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U=
 | 
					github.com/matoous/go-nanoid v1.5.1/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U=
 | 
				
			||||||
 | 
					github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 | 
				
			||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 | 
					github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
 | 
				
			||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
					github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
				
			||||||
 | 
					github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 | 
				
			||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
 | 
					github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
 | 
				
			||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
 | 
					github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
 | 
				
			||||||
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
 | 
					 | 
				
			||||||
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
 | 
					 | 
				
			||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
 | 
					github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
 | 
				
			||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
 | 
					github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
 | 
				
			||||||
go.unistack.org/micro-codec-json/v4 v4.1.0 h1:iydeSkt3ee7IPU0dHHKlGN97lw+YFQasBk9rdv0woYA=
 | 
					go.unistack.org/micro-codec-json/v3 v3.10.3 h1:FwSBfJswov30Dyqxp1XfQW1EG4h77uTEe/VGflg6XlY=
 | 
				
			||||||
go.unistack.org/micro-codec-json/v4 v4.1.0/go.mod h1:aUg86elSlURSynTAetDAAXj/VzFDwwcg92QNrRzcvrM=
 | 
					go.unistack.org/micro-codec-json/v3 v3.10.3/go.mod h1:26OK5MizMNKhspGC6PRVwpDIp5w1GmRb0nE5eRWWDxA=
 | 
				
			||||||
go.unistack.org/micro-proto/v4 v4.1.0 h1:qPwL2n/oqh9RE3RTTDgt28XK3QzV597VugQPaw9lKUk=
 | 
					go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q=
 | 
				
			||||||
go.unistack.org/micro-proto/v4 v4.1.0/go.mod h1:ArmK7o+uFvxSY3dbJhKBBX4Pm1rhWdLEFf3LxBrMtec=
 | 
					go.unistack.org/micro-proto/v3 v3.4.1/go.mod h1:okx/cnOhzuCX0ggl/vToatbCupi0O44diiiLLsZ93Zo=
 | 
				
			||||||
go.unistack.org/micro/v4 v4.1.19 h1:LKpmSPYvX5B9AkFD7JqMU/U06v5yEWn2bsCG/YKZtZI=
 | 
					go.unistack.org/micro/v3 v3.11.48 h1:lHJYSHU2z1TTcuswItGwG7cZXN6n04EFqY7lk/0gA7w=
 | 
				
			||||||
go.unistack.org/micro/v4 v4.1.19/go.mod h1:xleO2M5Yxh4s6I+RUcLrEpUjobefh+71ctrdIfn7TUs=
 | 
					go.unistack.org/micro/v3 v3.11.48/go.mod h1:fDQ8Mu9wubaFP0L8hNQlpzHiEnWN0wbOlawN9HYo0N4=
 | 
				
			||||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
 | 
					golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
 | 
				
			||||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
 | 
					golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
 | 
				
			||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
 | 
					golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
 | 
				
			||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 | 
					golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
 | 
				
			||||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
 | 
					golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
 | 
				
			||||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
 | 
					golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
 | 
				
			||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg=
 | 
					google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4=
 | 
				
			||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
 | 
					google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
 | 
				
			||||||
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
 | 
					google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
 | 
				
			||||||
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
 | 
					google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
 | 
				
			||||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
 | 
					google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
 | 
				
			||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
 | 
					google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
					gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
					gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								message.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								message.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					package http
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
 | 
						"go.unistack.org/micro/v3/metadata"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type httpMessage struct {
 | 
				
			||||||
 | 
						topic   string
 | 
				
			||||||
 | 
						payload interface{}
 | 
				
			||||||
 | 
						opts    client.MessageOptions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *httpMessage) Topic() string {
 | 
				
			||||||
 | 
						return m.topic
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *httpMessage) Payload() interface{} {
 | 
				
			||||||
 | 
						return m.payload
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *httpMessage) ContentType() string {
 | 
				
			||||||
 | 
						return m.opts.ContentType
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *httpMessage) Metadata() metadata.Metadata {
 | 
				
			||||||
 | 
						return m.opts.Metadata
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -7,7 +7,7 @@ import (
 | 
				
			|||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro/v4/client"
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// --------------------------------------------- HTTPClient option -----------------------------------------------------
 | 
					// --------------------------------------------- HTTPClient option -----------------------------------------------------
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
package http
 | 
					package http
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"go.unistack.org/micro/v4/client"
 | 
						"go.unistack.org/micro/v3/client"
 | 
				
			||||||
	"go.unistack.org/micro/v4/codec"
 | 
						"go.unistack.org/micro/v3/codec"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type httpRequest struct {
 | 
					type httpRequest struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/require"
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"go.unistack.org/micro-client-http/v4/status"
 | 
						"go.unistack.org/micro-client-http/v3/status"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type fakeError struct{ s *status.Status }
 | 
					type fakeError struct{ s *status.Status }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user