mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-22 17:42:14 +08:00
Merge branch 'master' into tree-from-httprouter
This commit is contained in:
commit
dfbfeb9e55
3
Makefile
3
Makefile
@ -1,5 +1,6 @@
|
|||||||
GOFMT ?= gofmt "-s"
|
GOFMT ?= gofmt "-s"
|
||||||
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
||||||
|
VETPACKAGES ?= $(shell go list ./... | grep -v /vendor/ | grep -v /examples/)
|
||||||
GOFILES := $(shell find . -name "*.go" -type f -not -path "./vendor/*")
|
GOFILES := $(shell find . -name "*.go" -type f -not -path "./vendor/*")
|
||||||
|
|
||||||
all: install
|
all: install
|
||||||
@ -26,7 +27,7 @@ fmt-check:
|
|||||||
fi;
|
fi;
|
||||||
|
|
||||||
vet:
|
vet:
|
||||||
go vet $(PACKAGES)
|
go vet $(VETPACKAGES)
|
||||||
|
|
||||||
deps:
|
deps:
|
||||||
@hash govendor > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
@hash govendor > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||||
|
50
README.md
50
README.md
@ -54,6 +54,7 @@ Gin is a web framework written in Go (Golang). It features a martini-like API wi
|
|||||||
- [Build a single binary with templates](#build-a-single-binary-with-templates)
|
- [Build a single binary with templates](#build-a-single-binary-with-templates)
|
||||||
- [Bind form-data request with custom struct](#bind-form-data-request-with-custom-struct)
|
- [Bind form-data request with custom struct](#bind-form-data-request-with-custom-struct)
|
||||||
- [Try to bind body into different structs](#try-to-bind-body-into-different-structs)
|
- [Try to bind body into different structs](#try-to-bind-body-into-different-structs)
|
||||||
|
- [http2 server push](#http2-server-push)
|
||||||
- [Testing](#testing)
|
- [Testing](#testing)
|
||||||
- [Users](#users--)
|
- [Users](#users--)
|
||||||
|
|
||||||
@ -1656,6 +1657,55 @@ enough to call binding at once.
|
|||||||
can be called by `c.ShouldBind()` multiple times without any damage to
|
can be called by `c.ShouldBind()` multiple times without any damage to
|
||||||
performance (See [#1341](https://github.com/gin-gonic/gin/pull/1341)).
|
performance (See [#1341](https://github.com/gin-gonic/gin/pull/1341)).
|
||||||
|
|
||||||
|
### http2 server push
|
||||||
|
|
||||||
|
http.Pusher is supported only **go1.8+**. See the [golang blog](https://blog.golang.org/h2push) for detail information.
|
||||||
|
|
||||||
|
[embedmd]:# (examples/http-pusher/main.go go)
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var html = template.Must(template.New("https").Parse(`
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Https Test</title>
|
||||||
|
<script src="/assets/app.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 style="color:red;">Welcome, Ginner!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`))
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := gin.Default()
|
||||||
|
r.Static("/assets", "./assets")
|
||||||
|
r.SetHTMLTemplate(html)
|
||||||
|
|
||||||
|
r.GET("/", func(c *gin.Context) {
|
||||||
|
if pusher := c.Writer.Pusher(); pusher != nil {
|
||||||
|
// use pusher.Push() to do server push
|
||||||
|
if err := pusher.Push("/assets/app.js", nil); err != nil {
|
||||||
|
log.Printf("Failed to push: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.HTML(200, "https", gin.H{
|
||||||
|
"status": "success",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen and Server in https://127.0.0.1:8080
|
||||||
|
r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
The `net/http/httptest` package is preferable way for HTTP testing.
|
The `net/http/httptest` package is preferable way for HTTP testing.
|
||||||
|
10
context.go
Executable file → Normal file
10
context.go
Executable file → Normal file
@ -539,14 +539,10 @@ func (c *Context) ShouldBindBodyWith(
|
|||||||
func (c *Context) ClientIP() string {
|
func (c *Context) ClientIP() string {
|
||||||
if c.engine.ForwardedByClientIP {
|
if c.engine.ForwardedByClientIP {
|
||||||
clientIP := c.requestHeader("X-Forwarded-For")
|
clientIP := c.requestHeader("X-Forwarded-For")
|
||||||
if index := strings.IndexByte(clientIP, ','); index >= 0 {
|
clientIP = strings.TrimSpace(strings.Split(clientIP, ",")[0])
|
||||||
clientIP = clientIP[0:index]
|
if clientIP == "" {
|
||||||
|
clientIP = strings.TrimSpace(c.requestHeader("X-Real-Ip"))
|
||||||
}
|
}
|
||||||
clientIP = strings.TrimSpace(clientIP)
|
|
||||||
if clientIP != "" {
|
|
||||||
return clientIP
|
|
||||||
}
|
|
||||||
clientIP = strings.TrimSpace(c.requestHeader("X-Real-Ip"))
|
|
||||||
if clientIP != "" {
|
if clientIP != "" {
|
||||||
return clientIP
|
return clientIP
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ set -e
|
|||||||
|
|
||||||
echo "mode: count" > coverage.out
|
echo "mode: count" > coverage.out
|
||||||
|
|
||||||
for d in $(go list ./... | grep -E 'gin$|binding$|render$'); do
|
for d in $(go list ./... | grep -E 'gin$|binding$|render$' | grep -v 'examples'); do
|
||||||
go test -v -covermode=count -coverprofile=profile.out $d
|
go test -v -covermode=count -coverprofile=profile.out $d
|
||||||
if [ -f profile.out ]; then
|
if [ -f profile.out ]; then
|
||||||
cat profile.out | grep -v "mode:" >> coverage.out
|
cat profile.out | grep -v "mode:" >> coverage.out
|
||||||
|
19
examples/grpc/README.md
Normal file
19
examples/grpc/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
## How to run this example
|
||||||
|
|
||||||
|
1. run grpc server
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ go run grpc/server.go
|
||||||
|
```
|
||||||
|
|
||||||
|
2. run gin server
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ go run gin/main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
3. use curl command to test it
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ curl -v 'http://localhost:8052/rest/n/thinkerou'
|
||||||
|
```
|
46
examples/grpc/gin/main.go
Normal file
46
examples/grpc/gin/main.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
pb "github.com/gin-gonic/gin/examples/grpc/pb"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Set up a connection to the server.
|
||||||
|
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("did not connect: %v", err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
client := pb.NewGreeterClient(conn)
|
||||||
|
|
||||||
|
// Set up a http setver.
|
||||||
|
r := gin.Default()
|
||||||
|
r.GET("/rest/n/:name", func(c *gin.Context) {
|
||||||
|
name := c.Param("name")
|
||||||
|
|
||||||
|
// Contact the server and print out its response.
|
||||||
|
req := &pb.HelloRequest{Name: name}
|
||||||
|
res, err := client.SayHello(c, req)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
"error": err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"result": fmt.Sprint(res.Message),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Run http server
|
||||||
|
if err := r.Run(":8052"); err != nil {
|
||||||
|
log.Fatalf("could not run server: %v", err)
|
||||||
|
}
|
||||||
|
}
|
34
examples/grpc/grpc/server.go
Normal file
34
examples/grpc/grpc/server.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
pb "github.com/gin-gonic/gin/examples/grpc/pb"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/reflection"
|
||||||
|
)
|
||||||
|
|
||||||
|
// server is used to implement helloworld.GreeterServer.
|
||||||
|
type server struct{}
|
||||||
|
|
||||||
|
// SayHello implements helloworld.GreeterServer
|
||||||
|
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
|
||||||
|
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
lis, err := net.Listen("tcp", ":50051")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to listen: %v", err)
|
||||||
|
}
|
||||||
|
s := grpc.NewServer()
|
||||||
|
pb.RegisterGreeterServer(s, &server{})
|
||||||
|
|
||||||
|
// Register reflection service on gRPC server.
|
||||||
|
reflection.Register(s)
|
||||||
|
if err := s.Serve(lis); err != nil {
|
||||||
|
log.Fatalf("failed to serve: %v", err)
|
||||||
|
}
|
||||||
|
}
|
151
examples/grpc/pb/helloworld.pb.go
Normal file
151
examples/grpc/pb/helloworld.pb.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// Code generated by protoc-gen-go.
|
||||||
|
// source: helloworld.proto
|
||||||
|
// DO NOT EDIT!
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package helloworld is a generated protocol buffer package.
|
||||||
|
|
||||||
|
It is generated from these files:
|
||||||
|
helloworld.proto
|
||||||
|
|
||||||
|
It has these top-level messages:
|
||||||
|
HelloRequest
|
||||||
|
HelloReply
|
||||||
|
*/
|
||||||
|
package helloworld
|
||||||
|
|
||||||
|
import proto "github.com/golang/protobuf/proto"
|
||||||
|
import fmt "fmt"
|
||||||
|
import math "math"
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "golang.org/x/net/context"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the proto package it is being compiled against.
|
||||||
|
// A compilation error at this line likely means your copy of the
|
||||||
|
// proto package needs to be updated.
|
||||||
|
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||||
|
|
||||||
|
// The request message containing the user's name.
|
||||||
|
type HelloRequest struct {
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *HelloRequest) Reset() { *m = HelloRequest{} }
|
||||||
|
func (m *HelloRequest) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*HelloRequest) ProtoMessage() {}
|
||||||
|
func (*HelloRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||||
|
|
||||||
|
// The response message containing the greetings
|
||||||
|
type HelloReply struct {
|
||||||
|
Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *HelloReply) Reset() { *m = HelloReply{} }
|
||||||
|
func (m *HelloReply) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*HelloReply) ProtoMessage() {}
|
||||||
|
func (*HelloReply) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterType((*HelloRequest)(nil), "helloworld.HelloRequest")
|
||||||
|
proto.RegisterType((*HelloReply)(nil), "helloworld.HelloReply")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ context.Context
|
||||||
|
var _ grpc.ClientConn
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
const _ = grpc.SupportPackageIsVersion4
|
||||||
|
|
||||||
|
// Client API for Greeter service
|
||||||
|
|
||||||
|
type GreeterClient interface {
|
||||||
|
// Sends a greeting
|
||||||
|
SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type greeterClient struct {
|
||||||
|
cc *grpc.ClientConn
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGreeterClient(cc *grpc.ClientConn) GreeterClient {
|
||||||
|
return &greeterClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
|
||||||
|
out := new(HelloReply)
|
||||||
|
err := grpc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, c.cc, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server API for Greeter service
|
||||||
|
|
||||||
|
type GreeterServer interface {
|
||||||
|
// Sends a greeting
|
||||||
|
SayHello(context.Context, *HelloRequest) (*HelloReply, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterGreeterServer(s *grpc.Server, srv GreeterServer) {
|
||||||
|
s.RegisterService(&_Greeter_serviceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(HelloRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(GreeterServer).SayHello(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/helloworld.Greeter/SayHello",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _Greeter_serviceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "helloworld.Greeter",
|
||||||
|
HandlerType: (*GreeterServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "SayHello",
|
||||||
|
Handler: _Greeter_SayHello_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "helloworld.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { proto.RegisterFile("helloworld.proto", fileDescriptor0) }
|
||||||
|
|
||||||
|
var fileDescriptor0 = []byte{
|
||||||
|
// 174 bytes of a gzipped FileDescriptorProto
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9,
|
||||||
|
0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88,
|
||||||
|
0x28, 0x29, 0x71, 0xf1, 0x78, 0x80, 0x78, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42,
|
||||||
|
0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x92,
|
||||||
|
0x1a, 0x17, 0x17, 0x54, 0x4d, 0x41, 0x4e, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x6a, 0x71, 0x71,
|
||||||
|
0x62, 0x3a, 0x4c, 0x11, 0x8c, 0x6b, 0xe4, 0xc9, 0xc5, 0xee, 0x5e, 0x94, 0x9a, 0x5a, 0x92, 0x5a,
|
||||||
|
0x24, 0x64, 0xc7, 0xc5, 0x11, 0x9c, 0x58, 0x09, 0xd6, 0x25, 0x24, 0xa1, 0x87, 0xe4, 0x02, 0x64,
|
||||||
|
0xcb, 0xa4, 0xc4, 0xb0, 0xc8, 0x00, 0xad, 0x50, 0x62, 0x70, 0x32, 0xe0, 0x92, 0xce, 0xcc, 0xd7,
|
||||||
|
0x4b, 0x2f, 0x2a, 0x48, 0xd6, 0x4b, 0xad, 0x48, 0xcc, 0x2d, 0xc8, 0x49, 0x2d, 0x46, 0x52, 0xeb,
|
||||||
|
0xc4, 0x0f, 0x56, 0x1c, 0x0e, 0x62, 0x07, 0x80, 0xbc, 0x14, 0xc0, 0x98, 0xc4, 0x06, 0xf6, 0x9b,
|
||||||
|
0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x0f, 0xb7, 0xcd, 0xf2, 0xef, 0x00, 0x00, 0x00,
|
||||||
|
}
|
37
examples/grpc/pb/helloworld.proto
Normal file
37
examples/grpc/pb/helloworld.proto
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2015 gRPC authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_package = "io.grpc.examples.helloworld";
|
||||||
|
option java_outer_classname = "HelloWorldProto";
|
||||||
|
|
||||||
|
package helloworld;
|
||||||
|
|
||||||
|
// The greeting service definition.
|
||||||
|
service Greeter {
|
||||||
|
// Sends a greeting
|
||||||
|
rpc SayHello (HelloRequest) returns (HelloReply) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The request message containing the user's name.
|
||||||
|
message HelloRequest {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The response message containing the greetings
|
||||||
|
message HelloReply {
|
||||||
|
string message = 1;
|
||||||
|
}
|
1
examples/http-pusher/assets/app.js
Normal file
1
examples/http-pusher/assets/app.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
console.log("http2 pusher");
|
41
examples/http-pusher/main.go
Normal file
41
examples/http-pusher/main.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"html/template"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var html = template.Must(template.New("https").Parse(`
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Https Test</title>
|
||||||
|
<script src="/assets/app.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 style="color:red;">Welcome, Ginner!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`))
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
r := gin.Default()
|
||||||
|
r.Static("/assets", "./assets")
|
||||||
|
r.SetHTMLTemplate(html)
|
||||||
|
|
||||||
|
r.GET("/", func(c *gin.Context) {
|
||||||
|
if pusher := c.Writer.Pusher(); pusher != nil {
|
||||||
|
// use pusher.Push() to do server push
|
||||||
|
if err := pusher.Push("/assets/app.js", nil); err != nil {
|
||||||
|
log.Printf("Failed to push: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.HTML(200, "https", gin.H{
|
||||||
|
"status": "success",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen and Server in https://127.0.0.1:8080
|
||||||
|
r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")
|
||||||
|
}
|
15
examples/http-pusher/testdata/ca.pem
vendored
Normal file
15
examples/http-pusher/testdata/ca.pem
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV
|
||||||
|
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
|
||||||
|
aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla
|
||||||
|
Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
|
||||||
|
YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT
|
||||||
|
BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7
|
||||||
|
+L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu
|
||||||
|
g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd
|
||||||
|
Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV
|
||||||
|
HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau
|
||||||
|
sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m
|
||||||
|
oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG
|
||||||
|
Dfcog5wrJytaQ6UA0wE=
|
||||||
|
-----END CERTIFICATE-----
|
16
examples/http-pusher/testdata/server.key
vendored
Normal file
16
examples/http-pusher/testdata/server.key
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD
|
||||||
|
M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf
|
||||||
|
3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY
|
||||||
|
AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm
|
||||||
|
V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY
|
||||||
|
tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p
|
||||||
|
dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q
|
||||||
|
K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR
|
||||||
|
81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff
|
||||||
|
DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd
|
||||||
|
aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2
|
||||||
|
ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3
|
||||||
|
XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe
|
||||||
|
F98XJ7tIFfJq
|
||||||
|
-----END PRIVATE KEY-----
|
16
examples/http-pusher/testdata/server.pem
vendored
Normal file
16
examples/http-pusher/testdata/server.pem
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
|
||||||
|
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
|
||||||
|
dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
|
||||||
|
MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
|
||||||
|
BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
|
||||||
|
ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
|
||||||
|
LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
|
||||||
|
zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
|
||||||
|
9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
|
||||||
|
CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
|
||||||
|
em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
|
||||||
|
CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
|
||||||
|
hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
|
||||||
|
y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
|
||||||
|
-----END CERTIFICATE-----
|
2
path.go
2
path.go
@ -41,7 +41,7 @@ func cleanPath(p string) string {
|
|||||||
buf[0] = '/'
|
buf[0] = '/'
|
||||||
}
|
}
|
||||||
|
|
||||||
trailing := n > 2 && p[n-1] == '/'
|
trailing := n > 1 && p[n-1] == '/'
|
||||||
|
|
||||||
// A bit more clunky without a 'lazybuf' like the path package, but the loop
|
// A bit more clunky without a 'lazybuf' like the path package, but the loop
|
||||||
// gets completely inlined (bufApp). So in contrast to the path package this
|
// gets completely inlined (bufApp). So in contrast to the path package this
|
||||||
|
@ -24,6 +24,7 @@ var cleanTests = []struct {
|
|||||||
|
|
||||||
// missing root
|
// missing root
|
||||||
{"", "/"},
|
{"", "/"},
|
||||||
|
{"a/", "/a/"},
|
||||||
{"abc", "/abc"},
|
{"abc", "/abc"},
|
||||||
{"abc/def", "/abc/def"},
|
{"abc/def", "/abc/def"},
|
||||||
{"a/b/c", "/a/b/c"},
|
{"a/b/c", "/a/b/c"},
|
||||||
|
@ -16,7 +16,7 @@ const (
|
|||||||
defaultStatus = 200
|
defaultStatus = 200
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResponseWriter interface {
|
type responseWriterBase interface {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
http.Hijacker
|
http.Hijacker
|
||||||
http.Flusher
|
http.Flusher
|
||||||
|
12
response_writer_1.7.go
Normal file
12
response_writer_1.7.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// +build !go1.8
|
||||||
|
|
||||||
|
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gin
|
||||||
|
|
||||||
|
// ResponseWriter ...
|
||||||
|
type ResponseWriter interface {
|
||||||
|
responseWriterBase
|
||||||
|
}
|
25
response_writer_1.8.go
Normal file
25
response_writer_1.8.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// +build go1.8
|
||||||
|
|
||||||
|
// Copyright 2018 Gin Core Team. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ResponseWriter ...
|
||||||
|
type ResponseWriter interface {
|
||||||
|
responseWriterBase
|
||||||
|
// get the http.Pusher for server push
|
||||||
|
Pusher() http.Pusher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *responseWriter) Pusher() (pusher http.Pusher) {
|
||||||
|
if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
|
||||||
|
return pusher
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
61
vendor/vendor.json
vendored
61
vendor/vendor.json
vendored
@ -9,61 +9,30 @@
|
|||||||
"revision": "346938d642f2ec3594ed81d874461961cd0faa76",
|
"revision": "346938d642f2ec3594ed81d874461961cd0faa76",
|
||||||
"revisionTime": "2016-10-29T20:57:26Z"
|
"revisionTime": "2016-10-29T20:57:26Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "7c3FuEadBInl/4ExSrB7iJMXpe4=",
|
|
||||||
"path": "github.com/dustin/go-broadcast",
|
|
||||||
"revision": "3bdf6d4a7164a50bc19d5f230e2981d87d2584f1",
|
|
||||||
"revisionTime": "2014-06-27T04:00:55Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "QeKwBtN2df+j+4stw3bQJ6yO4EY=",
|
"checksumSHA1": "QeKwBtN2df+j+4stw3bQJ6yO4EY=",
|
||||||
"path": "github.com/gin-contrib/sse",
|
"path": "github.com/gin-contrib/sse",
|
||||||
"revision": "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae",
|
"revision": "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae",
|
||||||
"revisionTime": "2017-01-09T09:34:21Z"
|
"revisionTime": "2017-01-09T09:34:21Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "+vZNyF2MykVjenLg1TpjjgjthV0=",
|
|
||||||
"path": "github.com/gin-gonic/autotls",
|
|
||||||
"revision": "8ca25fbde72bb72a00466215b94b489c71fcb815",
|
|
||||||
"revisionTime": "2017-09-16T16:54:15Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "qlPUeFabwF4RKAOF1H+yBFU1Veg=",
|
"checksumSHA1": "qlPUeFabwF4RKAOF1H+yBFU1Veg=",
|
||||||
"path": "github.com/golang/protobuf/proto",
|
"path": "github.com/golang/protobuf/proto",
|
||||||
"revision": "5a0f697c9ed9d68fef0116532c6e05cfeae00e55",
|
"revision": "5a0f697c9ed9d68fef0116532c6e05cfeae00e55",
|
||||||
"revisionTime": "2017-06-01T23:02:30Z"
|
"revisionTime": "2017-06-01T23:02:30Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "Cq9h7eDNXXyR/qJPvO8/Rk4pmFg=",
|
|
||||||
"path": "github.com/jessevdk/go-assets",
|
|
||||||
"revision": "4f4301a06e153ff90e17793577ab6bf79f8dc5c5",
|
|
||||||
"revisionTime": "2016-09-21T14:41:39Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Ajh8TemnItg4nn+jKmVcsMRALBc=",
|
"checksumSHA1": "Ajh8TemnItg4nn+jKmVcsMRALBc=",
|
||||||
"path": "github.com/json-iterator/go",
|
"path": "github.com/json-iterator/go",
|
||||||
"revision": "36b14963da70d11297d313183d7e6388c8510e1e",
|
"revision": "36b14963da70d11297d313183d7e6388c8510e1e",
|
||||||
"revisionTime": "2017-08-29T15:58:51Z"
|
"revisionTime": "2017-08-29T15:58:51Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "9if9IBLsxkarJ804NPWAzgskIAk=",
|
|
||||||
"path": "github.com/manucorporat/stats",
|
|
||||||
"revision": "8f2d6ace262eba462e9beb552382c98be51d807b",
|
|
||||||
"revisionTime": "2015-05-31T20:46:25Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "U6lX43KDDlNOn+Z0Yyww+ZzHfFo=",
|
"checksumSHA1": "U6lX43KDDlNOn+Z0Yyww+ZzHfFo=",
|
||||||
"path": "github.com/mattn/go-isatty",
|
"path": "github.com/mattn/go-isatty",
|
||||||
"revision": "57fdcb988a5c543893cc61bce354a6e24ab70022",
|
"revision": "57fdcb988a5c543893cc61bce354a6e24ab70022",
|
||||||
"revisionTime": "2017-03-07T16:30:44Z"
|
"revisionTime": "2017-03-07T16:30:44Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "LuFv4/jlrmFNnDb/5SCSEPAM9vU=",
|
|
||||||
"comment": "v1.0.0",
|
|
||||||
"path": "github.com/pmezard/go-difflib/difflib",
|
|
||||||
"revision": "792786c7400a136282c1664665ae0a8db921c6c2",
|
|
||||||
"revisionTime": "2016-01-10T10:55:54Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Q2V7Zs3diLmLfmfbiuLpSxETSuY=",
|
"checksumSHA1": "Q2V7Zs3diLmLfmfbiuLpSxETSuY=",
|
||||||
"comment": "v1.1.4",
|
"comment": "v1.1.4",
|
||||||
@ -71,30 +40,12 @@
|
|||||||
"revision": "976c720a22c8eb4eb6a0b4348ad85ad12491a506",
|
"revision": "976c720a22c8eb4eb6a0b4348ad85ad12491a506",
|
||||||
"revisionTime": "2016-09-25T22:06:09Z"
|
"revisionTime": "2016-09-25T22:06:09Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "IopMW+arBezL5bqOfrVU6UEfn28=",
|
|
||||||
"path": "github.com/thinkerou/favicon",
|
|
||||||
"revision": "94a442a49da6e2d44bdd5e0d2e2e185c43a19d93",
|
|
||||||
"revisionTime": "2017-07-10T14:05:20Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "CoxdaTYdPZNJXr8mJfLxye428N0=",
|
"checksumSHA1": "CoxdaTYdPZNJXr8mJfLxye428N0=",
|
||||||
"path": "github.com/ugorji/go/codec",
|
"path": "github.com/ugorji/go/codec",
|
||||||
"revision": "c88ee250d0221a57af388746f5cf03768c21d6e2",
|
"revision": "c88ee250d0221a57af388746f5cf03768c21d6e2",
|
||||||
"revisionTime": "2017-02-15T20:11:44Z"
|
"revisionTime": "2017-02-15T20:11:44Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "W0j4I7QpxXlChjyhAojZmFjU6Bg=",
|
|
||||||
"path": "golang.org/x/crypto/acme",
|
|
||||||
"revision": "adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d",
|
|
||||||
"revisionTime": "2017-06-19T06:03:41Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"checksumSHA1": "TrKJW+flz7JulXU3sqnBJjGzgQc=",
|
|
||||||
"path": "golang.org/x/crypto/acme/autocert",
|
|
||||||
"revision": "adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d",
|
|
||||||
"revisionTime": "2017-06-19T06:03:41Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "9jjO5GjLa0XF/nfWihF02RoH4qc=",
|
"checksumSHA1": "9jjO5GjLa0XF/nfWihF02RoH4qc=",
|
||||||
"comment": "release-branch.go1.7",
|
"comment": "release-branch.go1.7",
|
||||||
@ -102,18 +53,6 @@
|
|||||||
"revision": "d4c55e66d8c3a2f3382d264b08e3e3454a66355a",
|
"revision": "d4c55e66d8c3a2f3382d264b08e3e3454a66355a",
|
||||||
"revisionTime": "2016-10-18T08:54:36Z"
|
"revisionTime": "2016-10-18T08:54:36Z"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"checksumSHA1": "S0DP7Pn7sZUmXc55IzZnNvERu6s=",
|
|
||||||
"path": "golang.org/x/sync/errgroup",
|
|
||||||
"revision": "8e0aa688b654ef28caa72506fa5ec8dba9fc7690",
|
|
||||||
"revisionTime": "2017-07-19T03:38:01Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"checksumSHA1": "TVEkpH3gq84iQ39I4R+mlDwjuVI=",
|
|
||||||
"path": "golang.org/x/sys/unix",
|
|
||||||
"revision": "99f16d856c9836c42d24e7ab64ea72916925fa97",
|
|
||||||
"revisionTime": "2017-03-08T15:04:45Z"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"checksumSHA1": "39V1idWER42Lmcmg2Uy40wMzOlo=",
|
"checksumSHA1": "39V1idWER42Lmcmg2Uy40wMzOlo=",
|
||||||
"comment": "v8.18.1",
|
"comment": "v8.18.1",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user