1 /*
2 * Copyright 2010 FatWire Corporation. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package tools.gsf.httpstatus;
18
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import javax.servlet.http.HttpServletResponse;
23 import javax.servlet.http.HttpServletResponseWrapper;
24 import java.io.IOException;
25
26 import static tools.gsf.httpstatus.HttpStatusStrings.X_FATWIRE_HEADER;
27 import static tools.gsf.httpstatus.HttpStatusStrings.X_FATWIRE_STATUS;
28
29 /**
30 * <p>
31 * A filter that transforms 2 special headers into a response status or response
32 * header. In a ContentServer XML element you can call
33 * ics.StreamHeader("X-Fatwire-Status","404") to set the response status for
34 * Satellite Server to 404.
35 * </p>
36 *
37 * @author Dolf Dijkstra
38 * @version 15 June 2009
39 */
40 public class HttpStatusFilterResponseWrapper extends HttpServletResponseWrapper {
41
42 private static Logger log = LoggerFactory.getLogger("tools.gsf.httpstatus.HttpStatusFilterResponseWrapper");
43
44 private int status = -1;
45
46 private final boolean sendError;
47
48 /**
49 * Class constructor instantiating the response object
50 *
51 * @param origResponse servlet response
52 * @param sendError flag to send an error
53 */
54 public HttpStatusFilterResponseWrapper(HttpServletResponse origResponse, boolean sendError) {
55 super(origResponse);
56 this.sendError = sendError;
57
58 }
59
60 /**
61 * This method sets the response header value and names. It just proxies the
62 * custom response header information if the environment is CS
63 * (ContentServer). If the environment is SS (Satellite Server) then the
64 * custom header information supplied as "X-FatWire-Header" and
65 * "X-FatWire-Status" is parsed and set in the response header accordingly
66 *
67 * @param hdrName Response header name
68 * @param hdrValue Response header value
69 */
70 public void setHeader(String hdrName, String hdrValue) {
71 if (log.isDebugEnabled()) {
72 log.debug("original setHeader " + hdrName + ": " + hdrValue);
73 }
74
75 if (X_FATWIRE_STATUS.equalsIgnoreCase(hdrName)) {
76 try {
77 status = Integer.parseInt(hdrValue);
78 } catch (Throwable t) {
79 log.warn("Exception parsing the " + hdrName + " header. " + t.getMessage());
80 }
81 if (status > 300) {
82 // TODO low priority: is sendRedirectNeeded for 302 or 301?
83 if (log.isDebugEnabled()) {
84 log.debug("setStatus to " + status + " from " + hdrName);
85 }
86 if (this.isCommitted()) {
87 log.debug("wanted to setStatus to " + status + " from " + hdrName
88 + " but the response is already committed");
89 }
90 if (sendError && status >= 400) {
91 try {
92 super.sendError(status);
93 } catch (IOException e) {
94 log.warn("Could not send error " + status + ".", e);
95 }
96 } else {
97 super.setStatus(status);
98 }
99 // ignore the header all together after the setStatus, so
100 // we are not leaking to the public
101
102 } else if (status != -1) {
103 log.debug("ignoring status header with value " + status + " from " + hdrName);
104 }
105 } else if (X_FATWIRE_HEADER.equalsIgnoreCase(hdrName)) {
106 // splitting header name/value based on passed in header value,
107 // pipe seperated;
108 String[] headers = hdrValue.split("\\|");
109 if (headers.length == 2 && headers[0] != null && headers[1] != null) {
110
111 super.setHeader(headers[0], headers[1]);
112 } else {
113 log.debug(hdrName + " could not be split into something useful. " + hdrValue);
114 }
115
116 } else {
117 super.setHeader(hdrName, hdrValue);
118 }
119
120 }
121
122 @Override
123 public void setStatus(int sc) {
124 if (status == -1) {
125 // only set it if we have not overridden it
126 super.setStatus(sc);
127 } else {
128 if (log.isTraceEnabled()) {
129 log.trace("setStatus " + sc + " is being ignored because " + X_FATWIRE_STATUS + " header set it to "
130 + status);
131 }
132
133 }
134 }
135
136 }// end of BufferedHttpResponseWrapper
137