Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
fb2b15a7
Commit
fb2b15a7
authored
Oct 21, 2014
by
alex
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replace custom proxy with httputil.ReverseProxy for kubecfg/kubectl.
Fixes #1149 - kubecfg proxy "411 Length Required" error on POST/PUT.
parent
d5377e4a
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
252 additions
and
126 deletions
+252
-126
kubecfg.go
cmd/kubecfg/kubecfg.go
+4
-1
request_test.go
pkg/client/request_test.go
+32
-0
proxy_server.go
pkg/kubecfg/proxy_server.go
+38
-43
proxy_server_test.go
pkg/kubecfg/proxy_server_test.go
+65
-18
cmd.go
pkg/kubectl/cmd/cmd.go
+7
-1
proxy.go
pkg/kubectl/cmd/proxy.go
+2
-1
proxy_server.go
pkg/kubectl/proxy_server.go
+39
-44
proxy_server_test.go
pkg/kubectl/proxy_server_test.go
+65
-18
No files found.
cmd/kubecfg/kubecfg.go
View file @
fb2b15a7
...
@@ -260,7 +260,10 @@ func main() {
...
@@ -260,7 +260,10 @@ func main() {
open
.
Start
(
"http://localhost:8001/static/"
)
open
.
Start
(
"http://localhost:8001/static/"
)
}()
}()
}
}
server
:=
kubecfg
.
NewProxyServer
(
*
www
,
kubeClient
)
server
,
err
:=
kubecfg
.
NewProxyServer
(
*
www
,
clientConfig
)
if
err
!=
nil
{
glog
.
Fatalf
(
"Error creating proxy server: %v"
,
err
)
}
glog
.
Fatal
(
server
.
Serve
())
glog
.
Fatal
(
server
.
Serve
())
}
}
...
...
pkg/client/request_test.go
View file @
fb2b15a7
...
@@ -271,6 +271,38 @@ func TestUnacceptableParamNames(t *testing.T) {
...
@@ -271,6 +271,38 @@ func TestUnacceptableParamNames(t *testing.T) {
}
}
}
}
func
TestBody
(
t
*
testing
.
T
)
{
const
data
=
"test payload"
f
,
err
:=
ioutil
.
TempFile
(
""
,
"test_body"
)
if
err
!=
nil
{
t
.
Fatalf
(
"TempFile error: %v"
,
err
)
}
if
_
,
err
:=
f
.
WriteString
(
data
);
err
!=
nil
{
t
.
Fatalf
(
"TempFile.WriteString error: %v"
,
err
)
}
f
.
Close
()
c
:=
NewOrDie
(
&
Config
{})
tests
:=
[]
interface
{}{[]
byte
(
data
),
f
.
Name
(),
strings
.
NewReader
(
data
)}
for
i
,
tt
:=
range
tests
{
r
:=
c
.
Post
()
.
Body
(
tt
)
if
r
.
err
!=
nil
{
t
.
Errorf
(
"%d: r.Body(%#v) error: %v"
,
i
,
tt
,
r
.
err
)
continue
}
buf
:=
make
([]
byte
,
len
(
data
))
if
_
,
err
:=
r
.
body
.
Read
(
buf
);
err
!=
nil
{
t
.
Errorf
(
"%d: r.body.Read error: %v"
,
i
,
err
)
continue
}
body
:=
string
(
buf
)
if
body
!=
data
{
t
.
Errorf
(
"%d: r.body = %q; want %q"
,
i
,
body
,
data
)
}
}
}
func
TestSetPollPeriod
(
t
*
testing
.
T
)
{
func
TestSetPollPeriod
(
t
*
testing
.
T
)
{
c
:=
NewOrDie
(
&
Config
{})
c
:=
NewOrDie
(
&
Config
{})
r
:=
c
.
Get
()
r
:=
c
.
Get
()
...
...
pkg/kubecfg/proxy_server.go
View file @
fb2b15a7
...
@@ -17,32 +17,37 @@ limitations under the License.
...
@@ -17,32 +17,37 @@ limitations under the License.
package
kubecfg
package
kubecfg
import
(
import
(
"fmt"
"net/http"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
)
)
// ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server.
// ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server.
type
ProxyServer
struct
{
type
ProxyServer
struct
{
Client
*
client
.
Client
httputil
.
ReverseProxy
}
func
newFileHandler
(
prefix
,
base
string
)
http
.
Handler
{
return
http
.
StripPrefix
(
prefix
,
http
.
FileServer
(
http
.
Dir
(
base
)))
}
}
// NewProxyServer creates and installs a new ProxyServer.
// NewProxyServer creates and installs a new ProxyServer.
// It automatically registers the created ProxyServer to http.DefaultServeMux.
// It automatically registers the created ProxyServer to http.DefaultServeMux.
func
NewProxyServer
(
filebase
string
,
kubeClient
*
client
.
Client
)
*
ProxyServer
{
func
NewProxyServer
(
filebase
string
,
cfg
*
client
.
Config
)
(
*
ProxyServer
,
error
)
{
server
:=
&
ProxyServer
{
prefix
:=
cfg
.
Prefix
Client
:
kubeClient
,
if
prefix
==
""
{
prefix
=
"/api"
}
target
,
err
:=
url
.
Parse
(
singleJoiningSlash
(
cfg
.
Host
,
prefix
))
if
err
!=
nil
{
return
nil
,
err
}
proxy
:=
newProxyServer
(
target
)
if
proxy
.
Transport
,
err
=
client
.
TransportFor
(
cfg
);
err
!=
nil
{
return
nil
,
err
}
}
http
.
Handle
(
"/api/"
,
server
)
http
.
Handle
(
"/api/"
,
http
.
StripPrefix
(
"/api/"
,
proxy
)
)
http
.
Handle
(
"/static/"
,
newFileHandler
(
"/static/"
,
filebase
))
http
.
Handle
(
"/static/"
,
newFileHandler
(
"/static/"
,
filebase
))
return
server
return
proxy
,
nil
}
}
// Serve starts the server (http.DefaultServeMux) on TCP port 8001, loops forever.
// Serve starts the server (http.DefaultServeMux) on TCP port 8001, loops forever.
...
@@ -50,37 +55,27 @@ func (s *ProxyServer) Serve() error {
...
@@ -50,37 +55,27 @@ func (s *ProxyServer) Serve() error {
return
http
.
ListenAndServe
(
":8001"
,
nil
)
return
http
.
ListenAndServe
(
":8001"
,
nil
)
}
}
func
(
s
*
ProxyServer
)
doError
(
w
http
.
ResponseWriter
,
err
error
)
{
func
newProxyServer
(
target
*
url
.
URL
)
*
ProxyServer
{
w
.
WriteHeader
(
http
.
StatusInternalServerError
)
director
:=
func
(
req
*
http
.
Request
)
{
w
.
Header
()
.
Add
(
"Content-type"
,
"application/json"
)
req
.
URL
.
Scheme
=
target
.
Scheme
data
,
_
:=
latest
.
Codec
.
Encode
(
&
api
.
Status
{
req
.
URL
.
Host
=
target
.
Host
Status
:
api
.
StatusFailure
,
req
.
URL
.
Path
=
singleJoiningSlash
(
target
.
Path
,
req
.
URL
.
Path
)
Message
:
fmt
.
Sprintf
(
"internal error: %#v"
,
err
),
}
})
return
&
ProxyServer
{
ReverseProxy
:
httputil
.
ReverseProxy
{
Director
:
director
}}
w
.
Write
(
data
)
}
}
func
(
s
*
ProxyServer
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
newFileHandler
(
prefix
,
base
string
)
http
.
Handler
{
url
:=
r
.
URL
return
http
.
StripPrefix
(
prefix
,
http
.
FileServer
(
http
.
Dir
(
base
)))
selector
:=
url
.
Query
()
.
Get
(
"labels"
)
}
fieldSelector
:=
url
.
Query
()
.
Get
(
"fields"
)
result
:=
s
.
Client
.
func
singleJoiningSlash
(
a
,
b
string
)
string
{
Verb
(
r
.
Method
)
.
aslash
:=
strings
.
HasSuffix
(
a
,
"/"
)
AbsPath
(
r
.
URL
.
Path
)
.
bslash
:=
strings
.
HasPrefix
(
b
,
"/"
)
ParseSelectorParam
(
"labels"
,
selector
)
.
switch
{
ParseSelectorParam
(
"fields"
,
fieldSelector
)
.
case
aslash
&&
bslash
:
Body
(
r
.
Body
)
.
return
a
+
b
[
1
:
]
Do
()
case
!
aslash
&&
!
bslash
:
if
result
.
Error
()
!=
nil
{
return
a
+
"/"
+
b
s
.
doError
(
w
,
result
.
Error
())
return
}
data
,
err
:=
result
.
Raw
()
if
err
!=
nil
{
s
.
doError
(
w
,
err
)
return
}
}
w
.
Header
()
.
Add
(
"Content-type"
,
"application/json"
)
return
a
+
b
w
.
WriteHeader
(
http
.
StatusOK
)
w
.
Write
(
data
)
}
}
pkg/kubecfg/proxy_server_test.go
View file @
fb2b15a7
...
@@ -17,43 +17,90 @@ limitations under the License.
...
@@ -17,43 +17,90 @@ limitations under the License.
package
kubecfg
package
kubecfg
import
(
import
(
"fmt"
"io/ioutil"
"io/ioutil"
"net/http"
"net/http"
"net/http/httptest"
"net/http/httptest"
"net/url"
"path/filepath"
"strings"
"testing"
"testing"
)
)
func
TestFileServing
(
t
*
testing
.
T
)
{
func
TestFileServing
(
t
*
testing
.
T
)
{
data
:=
"This is test data"
const
(
fname
=
"test.txt"
data
=
"This is test data"
)
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"data"
)
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"data"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected erro
r: %v"
,
err
)
t
.
Fatalf
(
"error creating tmp di
r: %v"
,
err
)
}
}
err
=
ioutil
.
WriteFile
(
dir
+
"/test.txt"
,
[]
byte
(
data
),
0755
)
if
err
:=
ioutil
.
WriteFile
(
filepath
.
Join
(
dir
,
fname
),
[]
byte
(
data
),
0755
);
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"error writing tmp file: %v"
,
err
)
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
}
prefix
:=
"/foo/"
const
prefix
=
"/foo/"
handler
:=
newFileHandler
(
prefix
,
dir
)
handler
:=
newFileHandler
(
prefix
,
dir
)
server
:=
httptest
.
NewServer
(
handler
)
server
:=
httptest
.
NewServer
(
handler
)
client
:=
http
.
Client
{}
defer
server
.
Close
()
req
,
err
:=
http
.
NewRequest
(
"GET"
,
server
.
URL
+
prefix
+
"test.txt"
,
nil
)
if
err
!=
nil
{
url
:=
server
.
URL
+
prefix
+
fname
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
res
,
err
:=
http
.
Get
(
url
)
}
res
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
t
.
Fatalf
(
"http.Get(%q) error: %v"
,
url
,
err
)
}
}
defer
res
.
Body
.
Close
()
defer
res
.
Body
.
Close
()
if
res
.
StatusCode
!=
http
.
StatusOK
{
t
.
Errorf
(
"res.StatusCode = %d; want %d"
,
res
.
StatusCode
,
http
.
StatusOK
)
}
b
,
err
:=
ioutil
.
ReadAll
(
res
.
Body
)
b
,
err
:=
ioutil
.
ReadAll
(
res
.
Body
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
t
.
Fatalf
(
"error reading resp body: %v"
,
err
)
}
if
res
.
StatusCode
!=
http
.
StatusOK
{
t
.
Errorf
(
"Unexpected status: %d"
,
res
.
StatusCode
)
}
}
if
string
(
b
)
!=
data
{
if
string
(
b
)
!=
data
{
t
.
Errorf
(
"Data doesn't match: %s vs %s"
,
string
(
b
),
data
)
t
.
Errorf
(
"have %q; want %q"
,
string
(
b
),
data
)
}
}
func
TestAPIRequests
(
t
*
testing
.
T
)
{
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
b
,
err
:=
ioutil
.
ReadAll
(
r
.
Body
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
http
.
StatusInternalServerError
)
return
}
fmt
.
Fprintf
(
w
,
"%s %s %s"
,
r
.
Method
,
r
.
RequestURI
,
string
(
b
))
}))
defer
ts
.
Close
()
// httptest.NewServer should always generate a valid URL.
target
,
_
:=
url
.
Parse
(
ts
.
URL
)
proxy
:=
newProxyServer
(
target
)
tests
:=
[]
struct
{
method
,
body
string
}{
{
"GET"
,
""
},
{
"DELETE"
,
""
},
{
"POST"
,
"test payload"
},
{
"PUT"
,
"test payload"
},
}
const
path
=
"/api/test?fields=ID%3Dfoo&labels=key%3Dvalue"
for
i
,
tt
:=
range
tests
{
r
,
err
:=
http
.
NewRequest
(
tt
.
method
,
path
,
strings
.
NewReader
(
tt
.
body
))
if
err
!=
nil
{
t
.
Errorf
(
"error creating request: %v"
,
err
)
continue
}
w
:=
httptest
.
NewRecorder
()
proxy
.
ServeHTTP
(
w
,
r
)
if
w
.
Code
!=
http
.
StatusOK
{
t
.
Errorf
(
"%d: proxy.ServeHTTP w.Code = %d; want %d"
,
i
,
w
.
Code
,
http
.
StatusOK
)
}
want
:=
strings
.
Join
([]
string
{
tt
.
method
,
path
,
tt
.
body
},
" "
)
if
w
.
Body
.
String
()
!=
want
{
t
.
Errorf
(
"%d: response body = %q; want %q"
,
i
,
w
.
Body
.
String
(),
want
)
}
}
}
}
}
pkg/kubectl/cmd/cmd.go
View file @
fb2b15a7
...
@@ -138,7 +138,7 @@ func getFlagInt(cmd *cobra.Command, flag string) int {
...
@@ -138,7 +138,7 @@ func getFlagInt(cmd *cobra.Command, flag string) int {
return
v
return
v
}
}
func
getKubeC
lient
(
cmd
*
cobra
.
Command
)
*
client
.
Client
{
func
getKubeC
onfig
(
cmd
*
cobra
.
Command
)
*
client
.
Config
{
config
:=
&
client
.
Config
{}
config
:=
&
client
.
Config
{}
var
host
string
var
host
string
...
@@ -183,6 +183,12 @@ func getKubeClient(cmd *cobra.Command) *client.Client {
...
@@ -183,6 +183,12 @@ func getKubeClient(cmd *cobra.Command) *client.Client {
// The API version (e.g. v1beta1), not the binary version.
// The API version (e.g. v1beta1), not the binary version.
config
.
Version
=
getFlagString
(
cmd
,
"api-version"
)
config
.
Version
=
getFlagString
(
cmd
,
"api-version"
)
return
config
}
func
getKubeClient
(
cmd
*
cobra
.
Command
)
*
client
.
Client
{
config
:=
getKubeConfig
(
cmd
)
// The binary version.
// The binary version.
matchVersion
:=
getFlagBool
(
cmd
,
"match-server-version"
)
matchVersion
:=
getFlagBool
(
cmd
,
"match-server-version"
)
...
...
pkg/kubectl/cmd/proxy.go
View file @
fb2b15a7
...
@@ -32,7 +32,8 @@ func NewCmdProxy(out io.Writer) *cobra.Command {
...
@@ -32,7 +32,8 @@ func NewCmdProxy(out io.Writer) *cobra.Command {
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
Run
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
port
:=
getFlagInt
(
cmd
,
"port"
)
port
:=
getFlagInt
(
cmd
,
"port"
)
glog
.
Infof
(
"Starting to serve on localhost:%d"
,
port
)
glog
.
Infof
(
"Starting to serve on localhost:%d"
,
port
)
server
:=
kubectl
.
NewProxyServer
(
getFlagString
(
cmd
,
"www"
),
getKubeClient
(
cmd
),
port
)
server
,
err
:=
kubectl
.
NewProxyServer
(
getFlagString
(
cmd
,
"www"
),
getKubeConfig
(
cmd
),
port
)
checkErr
(
err
)
glog
.
Fatal
(
server
.
Serve
())
glog
.
Fatal
(
server
.
Serve
())
},
},
}
}
...
...
pkg/kubectl/proxy_server.go
View file @
fb2b15a7
...
@@ -19,32 +19,37 @@ package kubectl
...
@@ -19,32 +19,37 @@ package kubectl
import
(
import
(
"fmt"
"fmt"
"net/http"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
)
)
// ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server.
// ProxyServer is a http.Handler which proxies Kubernetes APIs to remote API server.
type
ProxyServer
struct
{
type
ProxyServer
struct
{
Client
*
client
.
Client
httputil
.
ReverseProxy
Port
int
Port
int
}
func
newFileHandler
(
prefix
,
base
string
)
http
.
Handler
{
return
http
.
StripPrefix
(
prefix
,
http
.
FileServer
(
http
.
Dir
(
base
)))
}
}
// NewProxyServer creates and installs a new ProxyServer.
// NewProxyServer creates and installs a new ProxyServer.
// It automatically registers the created ProxyServer to http.DefaultServeMux.
// It automatically registers the created ProxyServer to http.DefaultServeMux.
func
NewProxyServer
(
filebase
string
,
kubeClient
*
client
.
Client
,
port
int
)
*
ProxyServer
{
func
NewProxyServer
(
filebase
string
,
cfg
*
client
.
Config
,
port
int
)
(
*
ProxyServer
,
error
)
{
server
:=
&
ProxyServer
{
prefix
:=
cfg
.
Prefix
Client
:
kubeClient
,
if
prefix
==
""
{
Port
:
port
,
prefix
=
"/api"
}
target
,
err
:=
url
.
Parse
(
singleJoiningSlash
(
cfg
.
Host
,
prefix
))
if
err
!=
nil
{
return
nil
,
err
}
proxy
:=
newProxyServer
(
target
)
if
proxy
.
Transport
,
err
=
client
.
TransportFor
(
cfg
);
err
!=
nil
{
return
nil
,
err
}
}
http
.
Handle
(
"/api/"
,
server
)
http
.
Handle
(
"/api/"
,
http
.
StripPrefix
(
"/api/"
,
proxy
)
)
http
.
Handle
(
"/static/"
,
newFileHandler
(
"/static/"
,
filebase
))
http
.
Handle
(
"/static/"
,
newFileHandler
(
"/static/"
,
filebase
))
return
server
return
proxy
,
nil
}
}
// Serve starts the server (http.DefaultServeMux) on TCP port 8001, loops forever.
// Serve starts the server (http.DefaultServeMux) on TCP port 8001, loops forever.
...
@@ -53,37 +58,27 @@ func (s *ProxyServer) Serve() error {
...
@@ -53,37 +58,27 @@ func (s *ProxyServer) Serve() error {
return
http
.
ListenAndServe
(
addr
,
nil
)
return
http
.
ListenAndServe
(
addr
,
nil
)
}
}
func
(
s
*
ProxyServer
)
doError
(
w
http
.
ResponseWriter
,
err
error
)
{
func
newProxyServer
(
target
*
url
.
URL
)
*
ProxyServer
{
w
.
WriteHeader
(
http
.
StatusInternalServerError
)
director
:=
func
(
req
*
http
.
Request
)
{
w
.
Header
()
.
Add
(
"Content-type"
,
"application/json"
)
req
.
URL
.
Scheme
=
target
.
Scheme
data
,
_
:=
latest
.
Codec
.
Encode
(
&
api
.
Status
{
req
.
URL
.
Host
=
target
.
Host
Status
:
api
.
StatusFailure
,
req
.
URL
.
Path
=
singleJoiningSlash
(
target
.
Path
,
req
.
URL
.
Path
)
Message
:
fmt
.
Sprintf
(
"internal error: %#v"
,
err
),
}
})
return
&
ProxyServer
{
ReverseProxy
:
httputil
.
ReverseProxy
{
Director
:
director
}}
w
.
Write
(
data
)
}
}
func
(
s
*
ProxyServer
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
func
newFileHandler
(
prefix
,
base
string
)
http
.
Handler
{
url
:=
r
.
URL
return
http
.
StripPrefix
(
prefix
,
http
.
FileServer
(
http
.
Dir
(
base
)))
selector
:=
url
.
Query
()
.
Get
(
"labels"
)
}
fieldSelector
:=
url
.
Query
()
.
Get
(
"fields"
)
result
:=
s
.
Client
.
func
singleJoiningSlash
(
a
,
b
string
)
string
{
Verb
(
r
.
Method
)
.
aslash
:=
strings
.
HasSuffix
(
a
,
"/"
)
AbsPath
(
r
.
URL
.
Path
)
.
bslash
:=
strings
.
HasPrefix
(
b
,
"/"
)
ParseSelectorParam
(
"labels"
,
selector
)
.
switch
{
ParseSelectorParam
(
"fields"
,
fieldSelector
)
.
case
aslash
&&
bslash
:
Body
(
r
.
Body
)
.
return
a
+
b
[
1
:
]
Do
()
case
!
aslash
&&
!
bslash
:
if
result
.
Error
()
!=
nil
{
return
a
+
"/"
+
b
s
.
doError
(
w
,
result
.
Error
())
return
}
data
,
err
:=
result
.
Raw
()
if
err
!=
nil
{
s
.
doError
(
w
,
err
)
return
}
}
w
.
Header
()
.
Add
(
"Content-type"
,
"application/json"
)
return
a
+
b
w
.
WriteHeader
(
http
.
StatusOK
)
w
.
Write
(
data
)
}
}
pkg/kubectl/proxy_server_test.go
View file @
fb2b15a7
...
@@ -17,43 +17,90 @@ limitations under the License.
...
@@ -17,43 +17,90 @@ limitations under the License.
package
kubectl
package
kubectl
import
(
import
(
"fmt"
"io/ioutil"
"io/ioutil"
"net/http"
"net/http"
"net/http/httptest"
"net/http/httptest"
"net/url"
"path/filepath"
"strings"
"testing"
"testing"
)
)
func
TestFileServing
(
t
*
testing
.
T
)
{
func
TestFileServing
(
t
*
testing
.
T
)
{
data
:=
"This is test data"
const
(
fname
=
"test.txt"
data
=
"This is test data"
)
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"data"
)
dir
,
err
:=
ioutil
.
TempDir
(
""
,
"data"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected erro
r: %v"
,
err
)
t
.
Fatalf
(
"error creating tmp di
r: %v"
,
err
)
}
}
err
=
ioutil
.
WriteFile
(
dir
+
"/test.txt"
,
[]
byte
(
data
),
0755
)
if
err
:=
ioutil
.
WriteFile
(
filepath
.
Join
(
dir
,
fname
),
[]
byte
(
data
),
0755
);
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"error writing tmp file: %v"
,
err
)
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
}
prefix
:=
"/foo/"
const
prefix
=
"/foo/"
handler
:=
newFileHandler
(
prefix
,
dir
)
handler
:=
newFileHandler
(
prefix
,
dir
)
server
:=
httptest
.
NewServer
(
handler
)
server
:=
httptest
.
NewServer
(
handler
)
client
:=
http
.
Client
{}
defer
server
.
Close
()
req
,
err
:=
http
.
NewRequest
(
"GET"
,
server
.
URL
+
prefix
+
"test.txt"
,
nil
)
if
err
!=
nil
{
url
:=
server
.
URL
+
prefix
+
fname
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
res
,
err
:=
http
.
Get
(
url
)
}
res
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
t
.
Fatalf
(
"http.Get(%q) error: %v"
,
url
,
err
)
}
}
defer
res
.
Body
.
Close
()
defer
res
.
Body
.
Close
()
if
res
.
StatusCode
!=
http
.
StatusOK
{
t
.
Errorf
(
"res.StatusCode = %d; want %d"
,
res
.
StatusCode
,
http
.
StatusOK
)
}
b
,
err
:=
ioutil
.
ReadAll
(
res
.
Body
)
b
,
err
:=
ioutil
.
ReadAll
(
res
.
Body
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
t
.
Fatalf
(
"error reading resp body: %v"
,
err
)
}
if
res
.
StatusCode
!=
http
.
StatusOK
{
t
.
Errorf
(
"Unexpected status: %d"
,
res
.
StatusCode
)
}
}
if
string
(
b
)
!=
data
{
if
string
(
b
)
!=
data
{
t
.
Errorf
(
"Data doesn't match: %s vs %s"
,
string
(
b
),
data
)
t
.
Errorf
(
"have %q; want %q"
,
string
(
b
),
data
)
}
}
func
TestAPIRequests
(
t
*
testing
.
T
)
{
ts
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
b
,
err
:=
ioutil
.
ReadAll
(
r
.
Body
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
http
.
StatusInternalServerError
)
return
}
fmt
.
Fprintf
(
w
,
"%s %s %s"
,
r
.
Method
,
r
.
RequestURI
,
string
(
b
))
}))
defer
ts
.
Close
()
// httptest.NewServer should always generate a valid URL.
target
,
_
:=
url
.
Parse
(
ts
.
URL
)
proxy
:=
newProxyServer
(
target
)
tests
:=
[]
struct
{
method
,
body
string
}{
{
"GET"
,
""
},
{
"DELETE"
,
""
},
{
"POST"
,
"test payload"
},
{
"PUT"
,
"test payload"
},
}
const
path
=
"/api/test?fields=ID%3Dfoo&labels=key%3Dvalue"
for
i
,
tt
:=
range
tests
{
r
,
err
:=
http
.
NewRequest
(
tt
.
method
,
path
,
strings
.
NewReader
(
tt
.
body
))
if
err
!=
nil
{
t
.
Errorf
(
"error creating request: %v"
,
err
)
continue
}
w
:=
httptest
.
NewRecorder
()
proxy
.
ServeHTTP
(
w
,
r
)
if
w
.
Code
!=
http
.
StatusOK
{
t
.
Errorf
(
"%d: proxy.ServeHTTP w.Code = %d; want %d"
,
i
,
w
.
Code
,
http
.
StatusOK
)
}
want
:=
strings
.
Join
([]
string
{
tt
.
method
,
path
,
tt
.
body
},
" "
)
if
w
.
Body
.
String
()
!=
want
{
t
.
Errorf
(
"%d: response body = %q; want %q"
,
i
,
w
.
Body
.
String
(),
want
)
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment