| 
									
										
										
										
											2019-06-30 16:07:58 -06:00
										 |  |  | // Copyright 2015 Matthew Holt and The Caddy 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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 09:56:13 -06:00
										 |  |  | package caddyhttp | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2019-05-20 21:21:33 -06:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 12:37:06 -06:00
										 |  |  | 	"github.com/caddyserver/caddy/v2" | 
					
						
							| 
									
										
										
										
											2019-08-09 12:05:47 -06:00
										 |  |  | 	"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2019-08-21 10:46:35 -06:00
										 |  |  | 	caddy.RegisterModule(StaticResponse{}) | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-11 17:02:57 -06:00
										 |  |  | // StaticResponse implements a simple responder for static responses. | 
					
						
							|  |  |  | type StaticResponse struct { | 
					
						
							| 
									
										
										
										
											2019-12-23 12:45:35 -07:00
										 |  |  | 	// The HTTP status code to respond with. Can be an integer or, | 
					
						
							|  |  |  | 	// if needing to use a placeholder, a string. | 
					
						
							|  |  |  | 	StatusCode WeakString `json:"status_code,omitempty"` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Header fields to set on the response. | 
					
						
							|  |  |  | 	Headers http.Header `json:"headers,omitempty"` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// The response body. | 
					
						
							|  |  |  | 	Body string `json:"body,omitempty"` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If true, the server will close the client's connection | 
					
						
							|  |  |  | 	// after writing the response. | 
					
						
							|  |  |  | 	Close bool `json:"close,omitempty"` | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-21 10:46:35 -06:00
										 |  |  | // CaddyModule returns the Caddy module information. | 
					
						
							|  |  |  | func (StaticResponse) CaddyModule() caddy.ModuleInfo { | 
					
						
							|  |  |  | 	return caddy.ModuleInfo{ | 
					
						
							| 
									
										
										
										
											2019-12-10 13:36:46 -07:00
										 |  |  | 		ID:  "http.handlers.static_response", | 
					
						
							|  |  |  | 		New: func() caddy.Module { return new(StaticResponse) }, | 
					
						
							| 
									
										
										
										
											2019-08-21 10:46:35 -06:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-09 12:05:47 -06:00
										 |  |  | // UnmarshalCaddyfile sets up the handler from Caddyfile tokens. Syntax: | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2019-09-16 11:04:18 -06:00
										 |  |  | //     respond [<matcher>] <status> { | 
					
						
							| 
									
										
										
										
											2019-08-09 12:05:47 -06:00
										 |  |  | //         body <text> | 
					
						
							|  |  |  | //         close | 
					
						
							|  |  |  | //     } | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | func (s *StaticResponse) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { | 
					
						
							|  |  |  | 	for d.Next() { | 
					
						
							|  |  |  | 		var statusCodeStr string | 
					
						
							|  |  |  | 		if d.Args(&statusCodeStr) { | 
					
						
							|  |  |  | 			s.StatusCode = WeakString(statusCodeStr) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-10 19:21:52 -06:00
										 |  |  | 		for d.NextBlock(0) { | 
					
						
							| 
									
										
										
										
											2019-08-09 12:05:47 -06:00
										 |  |  | 			switch d.Val() { | 
					
						
							|  |  |  | 			case "body": | 
					
						
							|  |  |  | 				if s.Body != "" { | 
					
						
							|  |  |  | 					return d.Err("body already specified") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if !d.Args(&s.Body) { | 
					
						
							|  |  |  | 					return d.ArgErr() | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			case "close": | 
					
						
							|  |  |  | 				if s.Close { | 
					
						
							|  |  |  | 					return d.Err("close already specified") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				s.Close = true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-11 17:02:57 -06:00
										 |  |  | func (s StaticResponse) ServeHTTP(w http.ResponseWriter, r *http.Request, _ Handler) error { | 
					
						
							| 
									
										
										
										
											2019-12-29 13:12:52 -07:00
										 |  |  | 	repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-16 11:46:17 -06:00
										 |  |  | 	// close the connection after responding | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 	r.Close = s.Close | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-20 22:00:54 -06:00
										 |  |  | 	// set all headers | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 	for field, vals := range s.Headers { | 
					
						
							| 
									
										
										
										
											2019-05-20 10:59:20 -06:00
										 |  |  | 		field = repl.ReplaceAll(field, "") | 
					
						
							| 
									
										
										
										
											2019-06-21 14:36:26 -06:00
										 |  |  | 		newVals := make([]string, len(vals)) | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 		for i := range vals { | 
					
						
							| 
									
										
										
										
											2019-06-21 14:36:26 -06:00
										 |  |  | 			newVals[i] = repl.ReplaceAll(vals[i], "") | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-06-21 14:36:26 -06:00
										 |  |  | 		w.Header()[field] = newVals | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 19:59:17 -06:00
										 |  |  | 	// do not allow Go to sniff the content-type | 
					
						
							|  |  |  | 	if w.Header().Get("Content-Type") == "" { | 
					
						
							|  |  |  | 		w.Header()["Content-Type"] = nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-20 22:00:54 -06:00
										 |  |  | 	// get the status code | 
					
						
							| 
									
										
										
										
											2019-07-09 12:58:39 -06:00
										 |  |  | 	statusCode := http.StatusOK | 
					
						
							| 
									
										
										
										
											2019-07-11 17:02:57 -06:00
										 |  |  | 	if codeStr := s.StatusCode.String(); codeStr != "" { | 
					
						
							|  |  |  | 		intVal, err := strconv.Atoi(repl.ReplaceAll(codeStr, "")) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return Error(http.StatusInternalServerError, err) | 
					
						
							| 
									
										
										
										
											2019-05-20 21:21:33 -06:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-11 17:02:57 -06:00
										 |  |  | 		statusCode = intVal | 
					
						
							| 
									
										
										
										
											2019-05-20 21:21:33 -06:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-20 22:00:54 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// write headers | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 	w.WriteHeader(statusCode) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-20 22:00:54 -06:00
										 |  |  | 	// write response body | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 	if s.Body != "" { | 
					
						
							| 
									
										
										
										
											2019-10-28 14:39:37 -06:00
										 |  |  | 		fmt.Fprint(w, repl.ReplaceKnown(s.Body, "")) | 
					
						
							| 
									
										
										
										
											2019-05-04 13:21:20 -06:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-16 11:04:18 -06:00
										 |  |  | // Interface guards | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	_ MiddlewareHandler     = (*StaticResponse)(nil) | 
					
						
							|  |  |  | 	_ caddyfile.Unmarshaler = (*StaticResponse)(nil) | 
					
						
							|  |  |  | ) |