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 java.util.HashMap;
22  import java.util.Map;
23  
24  /**
25   * The request getMethod of HTTP or its derived protocols, such as
26   * <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
27   * <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>.
28   */
29  public class HttpMethod implements Comparable<HttpMethod> {
30      /**
31       * The OPTIONS getMethod represents a request for information about the communication options
32       * available on the request/response chain identified by the Request-URI. This getMethod allows
33       * the client to determine the options and/or requirements associated with a resource, or the
34       * capabilities of a server, without implying a resource action or initiating a resource
35       * retrieval.
36       */
37      public static final HttpMethod OPTIONS = new HttpMethod("OPTIONS", true);
38  
39      /**
40       * The GET getMethod means retrieve whatever information (in the form of an entity) is identified
41       * by the Request-URI.  If the Request-URI refers to a data-producing process, it is the
42       * produced data which shall be returned as the entity in the response and not the source text
43       * of the process, unless that text happens to be the output of the process.
44       */
45      public static final HttpMethod GET = new HttpMethod("GET", true);
46  
47      /**
48       * The HEAD getMethod is identical to GET except that the server MUST NOT return a message-body
49       * in the response.
50       */
51      public static final HttpMethod HEAD = new HttpMethod("HEAD", true);
52  
53      /**
54       * The POST getMethod is used to request that the origin server accept the entity enclosed in the
55       * request as a new subordinate of the resource identified by the Request-URI in the
56       * Request-Line.
57       */
58      public static final HttpMethod POST = new HttpMethod("POST", true);
59  
60      /**
61       * The PUT getMethod requests that the enclosed entity be stored under the supplied Request-URI.
62       */
63      public static final HttpMethod PUT = new HttpMethod("PUT", true);
64  
65      /**
66       * The PATCH getMethod requests that a set of changes described in the
67       * request entity be applied to the resource identified by the Request-URI.
68       */
69      public static final HttpMethod PATCH = new HttpMethod("PATCH", true);
70  
71      /**
72       * The DELETE getMethod requests that the origin server delete the resource identified by the
73       * Request-URI.
74       */
75      public static final HttpMethod DELETE = new HttpMethod("DELETE", true);
76  
77      /**
78       * The TRACE getMethod is used to invoke a remote, application-layer loop- back of the request
79       * message.
80       */
81      public static final HttpMethod TRACE = new HttpMethod("TRACE", true);
82  
83      /**
84       * This specification reserves the getMethod name CONNECT for use with a proxy that can dynamically
85       * switch to being a tunnel
86       */
87      public static final HttpMethod CONNECT = new HttpMethod("CONNECT", true);
88  
89      private static final Map<String, HttpMethod> methodMap =
90              new HashMap<String, HttpMethod>();
91  
92      static {
93          methodMap.put(OPTIONS.toString(), OPTIONS);
94          methodMap.put(GET.toString(), GET);
95          methodMap.put(HEAD.toString(), HEAD);
96          methodMap.put(POST.toString(), POST);
97          methodMap.put(PUT.toString(), PUT);
98          methodMap.put(PATCH.toString(), PATCH);
99          methodMap.put(DELETE.toString(), DELETE);
100         methodMap.put(TRACE.toString(), TRACE);
101         methodMap.put(CONNECT.toString(), CONNECT);
102     }
103 
104     /**
105      * Returns the {@link HttpMethod} represented by the specified name.
106      * If the specified name is a standard HTTP getMethod name, a cached instance
107      * will be returned.  Otherwise, a new instance will be returned.
108      */
109     public static HttpMethod valueOf(String name) {
110         if (name == null) {
111             throw new NullPointerException("name");
112         }
113 
114         name = name.trim();
115         if (name.isEmpty()) {
116             throw new IllegalArgumentException("empty name");
117         }
118 
119         HttpMethod result = methodMap.get(name);
120         if (result != null) {
121             return result;
122         } else {
123             return new HttpMethod(name);
124         }
125     }
126 
127     private final String name;
128     private final byte[] bytes;
129 
130     /**
131      * Creates a new HTTP getMethod with the specified name.  You will not need to
132      * create a new getMethod unless you are implementing a protocol derived from
133      * HTTP, such as
134      * <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
135      * <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>
136      */
137     public HttpMethod(String name) {
138         this(name, false);
139     }
140 
141     private HttpMethod(String name, boolean bytes) {
142         if (name == null) {
143             throw new NullPointerException("name");
144         }
145 
146         name = name.trim();
147         if (name.isEmpty()) {
148             throw new IllegalArgumentException("empty name");
149         }
150 
151         for (int i = 0; i < name.length(); i ++) {
152             if (Character.isISOControl(name.charAt(i)) ||
153                 Character.isWhitespace(name.charAt(i))) {
154                 throw new IllegalArgumentException("invalid character in name");
155             }
156         }
157 
158         this.name = name;
159         if (bytes) {
160             this.bytes = name.getBytes(CharsetUtil.US_ASCII);
161         } else {
162             this.bytes = null;
163         }
164     }
165 
166     /**
167      * Returns the name of this getMethod.
168      */
169     public String name() {
170         return name;
171     }
172 
173     @Override
174     public int hashCode() {
175         return name().hashCode();
176     }
177 
178     @Override
179     public boolean equals(Object o) {
180         if (!(o instanceof HttpMethod)) {
181             return false;
182         }
183 
184         HttpMethod that = (HttpMethod) o;
185         return name().equals(that.name());
186     }
187 
188     @Override
189     public String toString() {
190         return name();
191     }
192 
193     @Override
194     public int compareTo(HttpMethod o) {
195         return name().compareTo(o.name());
196     }
197 
198     void encode(ByteBuf buf) {
199         if (bytes == null) {
200             HttpHeaders.encodeAscii0(name, buf);
201         } else {
202             buf.writeBytes(bytes);
203         }
204     }
205 }