-
Notifications
You must be signed in to change notification settings - Fork 787
/
Method.scala
172 lines (155 loc) · 5.3 KB
/
Method.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
* Copyright 2013 http4s.org
*
* 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.
*/
package org.http4s
import cats.Hash
import cats.Order
import cats.Show
import cats.parse.Parser
import cats.syntax.all._
import org.http4s.internal.parsing.CommonRules
import org.http4s.util.Renderable
import org.http4s.util.Writer
import scala.util.hashing.MurmurHash3
/** An HTTP method.
*
* @param name The name of the method
*
* @param isSafe Request methods are considered "safe" if their defined
* semantics are essentially read-only; i.e., the client does not request, and
* does not expect, any state change on the origin server as a result of
* applying a safe method to a target resource.
*
* @param isIdempotent A request method is considered "idempotent" if the
* intended effect on the server of multiple identical requests with that
* method is the same as the effect for a single such request.
*
* @see [[https://datatracker.ietf.org/doc/html/rfc7231#section-4 RFC 7321, Section 4, Request Methods]]
* @see [[http://www.iana.org/assignments/http-methods/http-methods.xhtml IANA HTTP Method Registry]]
*/
final class Method private (val name: String, val isSafe: Boolean, val isIdempotent: Boolean)
extends Renderable
with Serializable {
override def equals(that: Any): Boolean =
that match {
case that: Method => this.name == that.name
case _ => false
}
override def hashCode(): Int = MurmurHash3.stringHash(name, Method.HashSeed)
override def toString(): String = name
override final def render(writer: Writer): writer.type = writer << name
}
object Method {
private final val HashSeed = 0x892abd01
def fromString(s: String): ParseResult[Method] =
allByKey.getOrElse(s, ParseResult.fromParser(parser, "Invalid method")(s))
private[http4s] val parser: Parser[Method] =
CommonRules.token.map(apply)
private def apply(name: String) =
new Method(name, isSafe = false, isIdempotent = false)
private def idempotent(name: String) =
new Method(name, isSafe = false, isIdempotent = true)
private def safe(name: String) =
new Method(name, isSafe = true, isIdempotent = true)
val ACL: Method = idempotent("ACL")
val `BASELINE-CONTROL`: Method = idempotent("BASELINE-CONTROL")
val BIND: Method = idempotent("BIND")
val CHECKIN: Method = idempotent("CHECKIN")
val CHECKOUT: Method = idempotent("CHECKOUT")
val CONNECT: Method = apply("CONNECT")
val COPY: Method = idempotent("COPY")
val DELETE: Method = idempotent("DELETE")
val GET: Method = safe("GET")
val HEAD: Method = safe("HEAD")
val LABEL: Method = idempotent("LABEL")
val LINK: Method = idempotent("LINK")
val LOCK: Method = apply("LOCK")
val MERGE: Method = idempotent("MERGE")
val MKACTIVITY: Method = idempotent("MKACTIVITY")
val MKCALENDAR: Method = idempotent("MKCALENDAR")
val MKCOL: Method = idempotent("MKCOL")
val MKREDIRECTREF: Method = idempotent("MKREDIRECTREF")
val MKWORKSPACE: Method = idempotent("MKWORKSPACE")
val MOVE: Method = idempotent("MOVE")
val OPTIONS: Method = safe("OPTIONS")
val ORDERPATCH: Method = idempotent("ORDERPATCH")
val PATCH: Method = apply("PATCH")
val POST: Method = apply("POST")
val PRI: Method = safe("PRI")
val PROPFIND: Method = safe("PROPFIND")
val PROPPATCH: Method = idempotent("PROPPATCH")
val PUT: Method = idempotent("PUT")
val REBIND: Method = idempotent("REBIND")
val REPORT: Method = safe("REPORT")
val SEARCH: Method = safe("SEARCH")
val TRACE: Method = safe("TRACE")
val UNBIND: Method = idempotent("UNBIND")
val UNCHECKOUT: Method = idempotent("UNCHECKOUT")
val UNLINK: Method = idempotent("UNLINK")
val UNLOCK: Method = idempotent("UNLOCK")
val UPDATE: Method = idempotent("UPDATE")
val UPDATEREDIRECTREF: Method = idempotent("UPDATEREDIRECTREF")
val `VERSION-CONTROL`: Method = idempotent("VERSION-CONTROL")
val all: List[Method] = List(
ACL,
`BASELINE-CONTROL`,
BIND,
CHECKIN,
CHECKOUT,
CONNECT,
COPY,
DELETE,
GET,
HEAD,
LABEL,
LINK,
LOCK,
MERGE,
MKACTIVITY,
MKCALENDAR,
MKCOL,
MKREDIRECTREF,
MKWORKSPACE,
MOVE,
OPTIONS,
ORDERPATCH,
PATCH,
POST,
PRI,
PROPFIND,
PROPPATCH,
PUT,
REBIND,
REPORT,
SEARCH,
TRACE,
UNBIND,
UNCHECKOUT,
UNLINK,
UNLOCK,
UPDATEREDIRECTREF,
`VERSION-CONTROL`,
)
private val allByKey: Map[String, Right[Nothing, Method]] = all.map(m => (m.name, Right(m))).toMap
implicit val catsInstancesForHttp4sMethod: Show[Method] with Hash[Method] with Order[Method] =
new Show[Method] with Hash[Method] with Order[Method] {
override def show(t: Method): String =
t.toString
override def hash(x: Method): Int =
x.hashCode
override def compare(x: Method, y: Method): Int =
x.name.compare(y.name)
}
}