View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. 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, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.codec.http;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.util.CharsetUtil;
20  
21  import static io.netty.handler.codec.http.HttpConstants.SP;
22  
23  /**
24   * The response code and its description of HTTP or its derived protocols, such as
25   * <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
26   * <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>.
27   */
28  public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
29  
30      /**
31       * 100 Continue
32       */
33      public static final HttpResponseStatus CONTINUE = new HttpResponseStatus(100, "Continue", true);
34  
35      /**
36       * 101 Switching Protocols
37       */
38      public static final HttpResponseStatus SWITCHING_PROTOCOLS =
39              new HttpResponseStatus(101, "Switching Protocols", true);
40  
41      /**
42       * 102 Processing (WebDAV, RFC2518)
43       */
44      public static final HttpResponseStatus PROCESSING = new HttpResponseStatus(102, "Processing", true);
45  
46      /**
47       * 200 OK
48       */
49      public static final HttpResponseStatus OK = new HttpResponseStatus(200, "OK", true);
50  
51      /**
52       * 201 Created
53       */
54      public static final HttpResponseStatus CREATED = new HttpResponseStatus(201, "Created", true);
55  
56      /**
57       * 202 Accepted
58       */
59      public static final HttpResponseStatus ACCEPTED = new HttpResponseStatus(202, "Accepted", true);
60  
61      /**
62       * 203 Non-Authoritative Information (since HTTP/1.1)
63       */
64      public static final HttpResponseStatus NON_AUTHORITATIVE_INFORMATION =
65              new HttpResponseStatus(203, "Non-Authoritative Information", true);
66  
67      /**
68       * 204 No Content
69       */
70      public static final HttpResponseStatus NO_CONTENT = new HttpResponseStatus(204, "No Content", true);
71  
72      /**
73       * 205 Reset Content
74       */
75      public static final HttpResponseStatus RESET_CONTENT = new HttpResponseStatus(205, "Reset Content", true);
76  
77      /**
78       * 206 Partial Content
79       */
80      public static final HttpResponseStatus PARTIAL_CONTENT = new HttpResponseStatus(206, "Partial Content", true);
81  
82      /**
83       * 207 Multi-Status (WebDAV, RFC2518)
84       */
85      public static final HttpResponseStatus MULTI_STATUS = new HttpResponseStatus(207, "Multi-Status", true);
86  
87      /**
88       * 300 Multiple Choices
89       */
90      public static final HttpResponseStatus MULTIPLE_CHOICES = new HttpResponseStatus(300, "Multiple Choices", true);
91  
92      /**
93       * 301 Moved Permanently
94       */
95      public static final HttpResponseStatus MOVED_PERMANENTLY = new HttpResponseStatus(301, "Moved Permanently", true);
96  
97      /**
98       * 302 Found
99       */
100     public static final HttpResponseStatus FOUND = new HttpResponseStatus(302, "Found", true);
101 
102     /**
103      * 303 See Other (since HTTP/1.1)
104      */
105     public static final HttpResponseStatus SEE_OTHER = new HttpResponseStatus(303, "See Other", true);
106 
107     /**
108      * 304 Not Modified
109      */
110     public static final HttpResponseStatus NOT_MODIFIED = new HttpResponseStatus(304, "Not Modified", true);
111 
112     /**
113      * 305 Use Proxy (since HTTP/1.1)
114      */
115     public static final HttpResponseStatus USE_PROXY = new HttpResponseStatus(305, "Use Proxy", true);
116 
117     /**
118      * 307 Temporary Redirect (since HTTP/1.1)
119      */
120     public static final HttpResponseStatus TEMPORARY_REDIRECT = new HttpResponseStatus(307, "Temporary Redirect", true);
121 
122     /**
123      * 400 Bad Request
124      */
125     public static final HttpResponseStatus BAD_REQUEST = new HttpResponseStatus(400, "Bad Request", true);
126 
127     /**
128      * 401 Unauthorized
129      */
130     public static final HttpResponseStatus UNAUTHORIZED = new HttpResponseStatus(401, "Unauthorized", true);
131 
132     /**
133      * 402 Payment Required
134      */
135     public static final HttpResponseStatus PAYMENT_REQUIRED = new HttpResponseStatus(402, "Payment Required", true);
136 
137     /**
138      * 403 Forbidden
139      */
140     public static final HttpResponseStatus FORBIDDEN = new HttpResponseStatus(403, "Forbidden", true);
141 
142     /**
143      * 404 Not Found
144      */
145     public static final HttpResponseStatus NOT_FOUND = new HttpResponseStatus(404, "Not Found", true);
146 
147     /**
148      * 405 Method Not Allowed
149      */
150     public static final HttpResponseStatus METHOD_NOT_ALLOWED = new HttpResponseStatus(405, "Method Not Allowed", true);
151 
152     /**
153      * 406 Not Acceptable
154      */
155     public static final HttpResponseStatus NOT_ACCEPTABLE = new HttpResponseStatus(406, "Not Acceptable", true);
156 
157     /**
158      * 407 Proxy Authentication Required
159      */
160     public static final HttpResponseStatus PROXY_AUTHENTICATION_REQUIRED =
161             new HttpResponseStatus(407, "Proxy Authentication Required", true);
162 
163     /**
164      * 408 Request Timeout
165      */
166     public static final HttpResponseStatus REQUEST_TIMEOUT = new HttpResponseStatus(408, "Request Timeout", true);
167 
168     /**
169      * 409 Conflict
170      */
171     public static final HttpResponseStatus CONFLICT = new HttpResponseStatus(409, "Conflict", true);
172 
173     /**
174      * 410 Gone
175      */
176     public static final HttpResponseStatus GONE = new HttpResponseStatus(410, "Gone", true);
177 
178     /**
179      * 411 Length Required
180      */
181     public static final HttpResponseStatus LENGTH_REQUIRED = new HttpResponseStatus(411, "Length Required", true);
182 
183     /**
184      * 412 Precondition Failed
185      */
186     public static final HttpResponseStatus PRECONDITION_FAILED =
187             new HttpResponseStatus(412, "Precondition Failed", true);
188 
189     /**
190      * 413 Request Entity Too Large
191      */
192     public static final HttpResponseStatus REQUEST_ENTITY_TOO_LARGE =
193             new HttpResponseStatus(413, "Request Entity Too Large", true);
194 
195     /**
196      * 414 Request-URI Too Long
197      */
198     public static final HttpResponseStatus REQUEST_URI_TOO_LONG =
199             new HttpResponseStatus(414, "Request-URI Too Long", true);
200 
201     /**
202      * 415 Unsupported Media Type
203      */
204     public static final HttpResponseStatus UNSUPPORTED_MEDIA_TYPE =
205             new HttpResponseStatus(415, "Unsupported Media Type", true);
206 
207     /**
208      * 416 Requested Range Not Satisfiable
209      */
210     public static final HttpResponseStatus REQUESTED_RANGE_NOT_SATISFIABLE =
211             new HttpResponseStatus(416, "Requested Range Not Satisfiable", true);
212 
213     /**
214      * 417 Expectation Failed
215      */
216     public static final HttpResponseStatus EXPECTATION_FAILED =
217             new HttpResponseStatus(417, "Expectation Failed", true);
218 
219     /**
220      * 422 Unprocessable Entity (WebDAV, RFC4918)
221      */
222     public static final HttpResponseStatus UNPROCESSABLE_ENTITY =
223             new HttpResponseStatus(422, "Unprocessable Entity", true);
224 
225     /**
226      * 423 Locked (WebDAV, RFC4918)
227      */
228     public static final HttpResponseStatus LOCKED =
229             new HttpResponseStatus(423, "Locked", true);
230 
231     /**
232      * 424 Failed Dependency (WebDAV, RFC4918)
233      */
234     public static final HttpResponseStatus FAILED_DEPENDENCY = new HttpResponseStatus(424, "Failed Dependency", true);
235 
236     /**
237      * 425 Unordered Collection (WebDAV, RFC3648)
238      */
239     public static final HttpResponseStatus UNORDERED_COLLECTION =
240             new HttpResponseStatus(425, "Unordered Collection", true);
241 
242     /**
243      * 426 Upgrade Required (RFC2817)
244      */
245     public static final HttpResponseStatus UPGRADE_REQUIRED = new HttpResponseStatus(426, "Upgrade Required", true);
246 
247     /**
248      * 428 Precondition Required (RFC6585)
249      */
250     public static final HttpResponseStatus PRECONDITION_REQUIRED =
251             new HttpResponseStatus(428, "Precondition Required", true);
252 
253     /**
254      * 429 Too Many Requests (RFC6585)
255      */
256     public static final HttpResponseStatus TOO_MANY_REQUESTS = new HttpResponseStatus(429, "Too Many Requests", true);
257 
258     /**
259      * 431 Request Header Fields Too Large (RFC6585)
260      */
261     public static final HttpResponseStatus REQUEST_HEADER_FIELDS_TOO_LARGE =
262             new HttpResponseStatus(431, "Request Header Fields Too Large", true);
263 
264     /**
265      * 500 Internal Server Error
266      */
267     public static final HttpResponseStatus INTERNAL_SERVER_ERROR =
268             new HttpResponseStatus(500, "Internal Server Error", true);
269 
270     /**
271      * 501 Not Implemented
272      */
273     public static final HttpResponseStatus NOT_IMPLEMENTED = new HttpResponseStatus(501, "Not Implemented", true);
274 
275     /**
276      * 502 Bad Gateway
277      */
278     public static final HttpResponseStatus BAD_GATEWAY = new HttpResponseStatus(502, "Bad Gateway", true);
279 
280     /**
281      * 503 Service Unavailable
282      */
283     public static final HttpResponseStatus SERVICE_UNAVAILABLE =
284             new HttpResponseStatus(503, "Service Unavailable", true);
285 
286     /**
287      * 504 Gateway Timeout
288      */
289     public static final HttpResponseStatus GATEWAY_TIMEOUT = new HttpResponseStatus(504, "Gateway Timeout", true);
290 
291     /**
292      * 505 HTTP Version Not Supported
293      */
294     public static final HttpResponseStatus HTTP_VERSION_NOT_SUPPORTED =
295             new HttpResponseStatus(505, "HTTP Version Not Supported", true);
296 
297     /**
298      * 506 Variant Also Negotiates (RFC2295)
299      */
300     public static final HttpResponseStatus VARIANT_ALSO_NEGOTIATES =
301             new HttpResponseStatus(506, "Variant Also Negotiates", true);
302 
303     /**
304      * 507 Insufficient Storage (WebDAV, RFC4918)
305      */
306     public static final HttpResponseStatus INSUFFICIENT_STORAGE =
307             new HttpResponseStatus(507, "Insufficient Storage", true);
308 
309     /**
310      * 510 Not Extended (RFC2774)
311      */
312     public static final HttpResponseStatus NOT_EXTENDED = new HttpResponseStatus(510, "Not Extended", true);
313 
314     /**
315      * 511 Network Authentication Required (RFC6585)
316      */
317     public static final HttpResponseStatus NETWORK_AUTHENTICATION_REQUIRED =
318             new HttpResponseStatus(511, "Network Authentication Required", true);
319 
320     /**
321      * Returns the {@link HttpResponseStatus} represented by the specified code.
322      * If the specified code is a standard HTTP getStatus code, a cached instance
323      * will be returned.  Otherwise, a new instance will be returned.
324      */
325     public static HttpResponseStatus valueOf(int code) {
326         switch (code) {
327         case 100:
328             return CONTINUE;
329         case 101:
330             return SWITCHING_PROTOCOLS;
331         case 102:
332             return PROCESSING;
333         case 200:
334             return OK;
335         case 201:
336             return CREATED;
337         case 202:
338             return ACCEPTED;
339         case 203:
340             return NON_AUTHORITATIVE_INFORMATION;
341         case 204:
342             return NO_CONTENT;
343         case 205:
344             return RESET_CONTENT;
345         case 206:
346             return PARTIAL_CONTENT;
347         case 207:
348             return MULTI_STATUS;
349         case 300:
350             return MULTIPLE_CHOICES;
351         case 301:
352             return MOVED_PERMANENTLY;
353         case 302:
354             return FOUND;
355         case 303:
356             return SEE_OTHER;
357         case 304:
358             return NOT_MODIFIED;
359         case 305:
360             return USE_PROXY;
361         case 307:
362             return TEMPORARY_REDIRECT;
363         case 400:
364             return BAD_REQUEST;
365         case 401:
366             return UNAUTHORIZED;
367         case 402:
368             return PAYMENT_REQUIRED;
369         case 403:
370             return FORBIDDEN;
371         case 404:
372             return NOT_FOUND;
373         case 405:
374             return METHOD_NOT_ALLOWED;
375         case 406:
376             return NOT_ACCEPTABLE;
377         case 407:
378             return PROXY_AUTHENTICATION_REQUIRED;
379         case 408:
380             return REQUEST_TIMEOUT;
381         case 409:
382             return CONFLICT;
383         case 410:
384             return GONE;
385         case 411:
386             return LENGTH_REQUIRED;
387         case 412:
388             return PRECONDITION_FAILED;
389         case 413:
390             return REQUEST_ENTITY_TOO_LARGE;
391         case 414:
392             return REQUEST_URI_TOO_LONG;
393         case 415:
394             return UNSUPPORTED_MEDIA_TYPE;
395         case 416:
396             return REQUESTED_RANGE_NOT_SATISFIABLE;
397         case 417:
398             return EXPECTATION_FAILED;
399         case 422:
400             return UNPROCESSABLE_ENTITY;
401         case 423:
402             return LOCKED;
403         case 424:
404             return FAILED_DEPENDENCY;
405         case 425:
406             return UNORDERED_COLLECTION;
407         case 426:
408             return UPGRADE_REQUIRED;
409         case 428:
410             return PRECONDITION_REQUIRED;
411         case 429:
412             return TOO_MANY_REQUESTS;
413         case 431:
414             return REQUEST_HEADER_FIELDS_TOO_LARGE;
415         case 500:
416             return INTERNAL_SERVER_ERROR;
417         case 501:
418             return NOT_IMPLEMENTED;
419         case 502:
420             return BAD_GATEWAY;
421         case 503:
422             return SERVICE_UNAVAILABLE;
423         case 504:
424             return GATEWAY_TIMEOUT;
425         case 505:
426             return HTTP_VERSION_NOT_SUPPORTED;
427         case 506:
428             return VARIANT_ALSO_NEGOTIATES;
429         case 507:
430             return INSUFFICIENT_STORAGE;
431         case 510:
432             return NOT_EXTENDED;
433         case 511:
434             return NETWORK_AUTHENTICATION_REQUIRED;
435         }
436 
437         final String reasonPhrase;
438 
439         if (code < 100) {
440             reasonPhrase = "Unknown Status";
441         } else if (code < 200) {
442             reasonPhrase = "Informational";
443         } else if (code < 300) {
444             reasonPhrase = "Successful";
445         } else if (code < 400) {
446             reasonPhrase = "Redirection";
447         } else if (code < 500) {
448             reasonPhrase = "Client Error";
449         } else if (code < 600) {
450             reasonPhrase = "Server Error";
451         } else {
452             reasonPhrase = "Unknown Status";
453         }
454 
455         return new HttpResponseStatus(code, reasonPhrase + " (" + code + ')');
456     }
457 
458     private final int code;
459 
460     private final String reasonPhrase;
461     private final byte[] bytes;
462 
463     /**
464      * Creates a new instance with the specified {@code code} and its
465      * {@code reasonPhrase}.
466      */
467     public HttpResponseStatus(int code, String reasonPhrase) {
468         this(code, reasonPhrase, false);
469     }
470 
471     private HttpResponseStatus(int code, String reasonPhrase, boolean bytes) {
472         if (code < 0) {
473             throw new IllegalArgumentException(
474                     "code: " + code + " (expected: 0+)");
475         }
476 
477         if (reasonPhrase == null) {
478             throw new NullPointerException("reasonPhrase");
479         }
480 
481         for (int i = 0; i < reasonPhrase.length(); i ++) {
482             char c = reasonPhrase.charAt(i);
483             // Check prohibited characters.
484             switch (c) {
485                 case '\n': case '\r':
486                     throw new IllegalArgumentException(
487                             "reasonPhrase contains one of the following prohibited characters: " +
488                                     "\\r\\n: " + reasonPhrase);
489             }
490         }
491 
492         this.code = code;
493         this.reasonPhrase = reasonPhrase;
494         if (bytes) {
495             this.bytes = (code + " " + reasonPhrase).getBytes(CharsetUtil.US_ASCII);
496         } else {
497             this.bytes = null;
498         }
499     }
500 
501     /**
502      * Returns the code of this {@link HttpResponseStatus}.
503      */
504     public int code() {
505         return code;
506     }
507 
508     /**
509      * Returns the reason phrase of this {@link HttpResponseStatus}.
510      */
511     public String reasonPhrase() {
512         return reasonPhrase;
513     }
514 
515     @Override
516     public int hashCode() {
517         return code();
518     }
519 
520     /**
521      * Equality of {@link HttpResponseStatus} only depends on {@link #code()}. The
522      * reason phrase is not considered for equality.
523      */
524     @Override
525     public boolean equals(Object o) {
526         if (!(o instanceof HttpResponseStatus)) {
527             return false;
528         }
529 
530         return code() == ((HttpResponseStatus) o).code();
531     }
532 
533     /**
534      * Equality of {@link HttpResponseStatus} only depends on {@link #code()}. The
535      * reason phrase is not considered for equality.
536      */
537     @Override
538     public int compareTo(HttpResponseStatus o) {
539         return code() - o.code();
540     }
541 
542     @Override
543     public String toString() {
544         return new StringBuilder(reasonPhrase.length() + 5)
545             .append(code)
546             .append(' ')
547             .append(reasonPhrase)
548             .toString();
549     }
550 
551     void encode(ByteBuf buf) {
552         if (bytes == null) {
553             HttpHeaders.encodeAscii0(String.valueOf(code()), buf);
554             buf.writeByte(SP);
555             HttpHeaders.encodeAscii0(String.valueOf(reasonPhrase()), buf);
556         } else {
557             buf.writeBytes(bytes);
558         }
559     }
560 }