contractful 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/API.md +142 -0
- data/ARCHITECTURE.md +134 -0
- data/AUTHORS +106 -0
- data/CODE_OF_CONDUCT.md +128 -0
- data/LICENSE +21 -0
- data/README.md +1290 -0
- data/SECURITY.md +67 -0
- data/bin/contractful +128 -0
- data/history.md +801 -0
- data/lib/contractful/abstract_response.rb +301 -0
- data/lib/contractful/circuit_breaker.rb +221 -0
- data/lib/contractful/connection_pool.rb +166 -0
- data/lib/contractful/contract/auth.rb +257 -0
- data/lib/contractful/contract/config.rb +93 -0
- data/lib/contractful/contract/definition.rb +295 -0
- data/lib/contractful/contract/dsl.rb +501 -0
- data/lib/contractful/contract/executor.rb +492 -0
- data/lib/contractful/contract/openapi_import.rb +1135 -0
- data/lib/contractful/contract/pagination.rb +218 -0
- data/lib/contractful/contract/param.rb +505 -0
- data/lib/contractful/contract/postman_import/auth.rb +39 -0
- data/lib/contractful/contract/postman_import/body.rb +87 -0
- data/lib/contractful/contract/postman_import/operation.rb +107 -0
- data/lib/contractful/contract/postman_import/scope.rb +37 -0
- data/lib/contractful/contract/postman_import/url.rb +80 -0
- data/lib/contractful/contract/postman_import.rb +164 -0
- data/lib/contractful/contract/response_field.rb +167 -0
- data/lib/contractful/contract/sequence.rb +432 -0
- data/lib/contractful/contract/swagger2/components.rb +84 -0
- data/lib/contractful/contract/swagger2/operations.rb +81 -0
- data/lib/contractful/contract/swagger2/parameters.rb +93 -0
- data/lib/contractful/contract/swagger2/references.rb +55 -0
- data/lib/contractful/contract/swagger2.rb +55 -0
- data/lib/contractful/contract.rb +85 -0
- data/lib/contractful/exceptions.rb +328 -0
- data/lib/contractful/notifications/active_support.rb +40 -0
- data/lib/contractful/notifications.rb +138 -0
- data/lib/contractful/pacer.rb +161 -0
- data/lib/contractful/params_array.rb +85 -0
- data/lib/contractful/payload.rb +340 -0
- data/lib/contractful/platform.rb +52 -0
- data/lib/contractful/rate_limit.rb +133 -0
- data/lib/contractful/raw_response.rb +70 -0
- data/lib/contractful/request.rb +1483 -0
- data/lib/contractful/resource.rb +189 -0
- data/lib/contractful/response.rb +109 -0
- data/lib/contractful/utils.rb +202 -0
- data/lib/contractful/version.rb +11 -0
- data/lib/contractful/windows/root_certs.rb +107 -0
- data/lib/contractful/windows.rb +9 -0
- data/lib/contractful.rb +233 -0
- metadata +244 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 895b5ad950f42663bcb0851f6acda44c9d2c183acacc97ff7fa10797f62e276a
|
|
4
|
+
data.tar.gz: 35164be35c17465d632673db30dca00724e978688e0e16ba8aae2b8ee887baae
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 79a242d59942954f6f86f1d4f887450410a3a75d4e431f14af20d121f553c35750c6db0567d99b65b3bf02242f62c16b7630296cd81fcbc2b2fc0b08401d1830
|
|
7
|
+
data.tar.gz: f72f2aeccabfd522c68dd6b03869646e22980bea34449b3b60c4c527a1b5b194ea3cb2f965e493ec76dac9e92472266a4f1f5a916ec9a0d67457582d145c68be
|
data/API.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# API — public surface reference
|
|
2
|
+
|
|
3
|
+
This document is the normative list of contractful's public API. Names
|
|
4
|
+
documented here are covered by semantic versioning: removing or changing one
|
|
5
|
+
requires a major release. Anything not listed here (underscore-prefixed
|
|
6
|
+
machinery like `__own_contract_config`, private helpers) is internal and may
|
|
7
|
+
change in any release. The contract-first layer is part of the public surface
|
|
8
|
+
and follows the same rules. Version markers in parentheses refer to the
|
|
9
|
+
upstream rest-client release line in which a feature first appeared;
|
|
10
|
+
contractful 0.1.0 ships all of them.
|
|
11
|
+
|
|
12
|
+
## Module-level entry points
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
Contractful.get(url, headers = {})
|
|
16
|
+
Contractful.post(url, payload, headers = {})
|
|
17
|
+
Contractful.put(url, payload, headers = {})
|
|
18
|
+
Contractful.patch(url, payload, headers = {})
|
|
19
|
+
Contractful.delete(url, headers = {})
|
|
20
|
+
Contractful.head(url, headers = {})
|
|
21
|
+
Contractful.options(url, headers = {})
|
|
22
|
+
Contractful::Request.execute(options) # full option surface, returns Response
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Non-2xx responses raise the mapped exception unless a block is given (block
|
|
26
|
+
form returns the response and lets the caller decide — see README "Result
|
|
27
|
+
handling").
|
|
28
|
+
|
|
29
|
+
## Request options
|
|
30
|
+
|
|
31
|
+
All accepted by `Request.execute` (and the corresponding per-call contract
|
|
32
|
+
meta options):
|
|
33
|
+
|
|
34
|
+
| Option | Meaning |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| `:method`, `:url` | Verb symbol and target URL (required) |
|
|
37
|
+
| `:payload` | Hash/ParamsArray (form or JSON), String, IO/stream, or multipart file parts |
|
|
38
|
+
| `:headers` | Header hash |
|
|
39
|
+
| `:user`, `:password` | Basic-auth credentials |
|
|
40
|
+
| `:timeout`, `:open_timeout`, `:read_timeout`, `:write_timeout` | Total and phase timeouts (seconds) |
|
|
41
|
+
| `:max_redirects` | Redirect cap (default 10) |
|
|
42
|
+
| `:ssl_ca_file`, `:ssl_client_cert`, `:ssl_client_key` | TLS trust and client identity |
|
|
43
|
+
| `:ssl_min_version`, `:ssl_max_version` | Protocol floor/ceiling; normalized via `normalize_ssl_version` (accepts `:TLSv1_2`-style symbols, `:TLS1_2`-style symbols and OpenSSL constants) |
|
|
44
|
+
| `:verify_ca` / `:verify_callback` | Certificate verification control |
|
|
45
|
+
| `:cookies` | Cookie hash or jar |
|
|
46
|
+
| `:persistent` | Use the keep-alive connection pool (2.3+) |
|
|
47
|
+
| `:max_retries`, `:retry_interval` | Automatic retry count and base delay (exponential backoff) (2.3+) |
|
|
48
|
+
| `:idempotent` | Repeating the request has the same effect as sending it once. Defaults to true for GET, HEAD, OPTIONS, TRACE, PUT and DELETE (RFC 9110), false otherwise. A positive `:max_retries` requires it to be true. |
|
|
49
|
+
| `:retry_after`, `:max_retry_after` | Honor server `Retry-After` and cap its value (2.5+) |
|
|
50
|
+
| `:log` | Per-request logger override |
|
|
51
|
+
| `:block_response` | Raw response handler |
|
|
52
|
+
|
|
53
|
+
## Resource
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
site = Contractful::Resource.new('https://api.example.com', user:, password:, headers:)
|
|
57
|
+
site['orders'].get # nested path resources
|
|
58
|
+
site['orders'].post(payload_hash) # same option surface as Request
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Response
|
|
62
|
+
|
|
63
|
+
`Contractful::Response` is a String-like object (`#body`, `#to_s`) plus:
|
|
64
|
+
|
|
65
|
+
| Method | Meaning |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `#code` / `#to_i` | HTTP status |
|
|
68
|
+
| `#headers` | Downcased header hash |
|
|
69
|
+
| `#raw_headers` | Original header block |
|
|
70
|
+
| `#history` | Redirect chain responses |
|
|
71
|
+
| `#cookies`, `#cookie_jar` | Set cookies as hash / jar |
|
|
72
|
+
| `#json(**opts)` | JSON.parse of the body (2.3+) |
|
|
73
|
+
| `#rate_limit` | Parsed `RateLimit` or `nil` when absent (2.5+) |
|
|
74
|
+
| `#rate_limited?` | Strict boolean: 429 or exhausted quota (2.5+) |
|
|
75
|
+
|
|
76
|
+
## Exceptions
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
Contractful::Exception < RuntimeError # .response .http_code .http_body .http_headers .retryable?
|
|
80
|
+
├── ExceptionWithResponse # retryable? = status in RETRIABLE_STATUSES
|
|
81
|
+
│ ├── RequestFailed # unmapped failure statuses
|
|
82
|
+
│ │ └── one class per HTTP status: NotFound, Unauthorized, Conflict,
|
|
83
|
+
│ │ TooManyRequests, InternalServerError, ... (+ legacy aliases)
|
|
84
|
+
│ └── Exceptions::Timeout < RequestTimeout
|
|
85
|
+
│ ├── OpenTimeout ├── ReadTimeout └── WriteTimeout (2.3+)
|
|
86
|
+
├── ServerBrokeConnection
|
|
87
|
+
└── SSLCertificateNotVerified
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Classification: `Contractful::Exceptions::RETRIABLE_STATUSES` is
|
|
91
|
+
`[408, 425, 429, 500, 502, 503, 504]`; `Exceptions.retryable?(status_or_exception)`
|
|
92
|
+
also classifies network errors (`SocketError`, `Errno::*`, `Net::*Timeout`,
|
|
93
|
+
`::Timeout::Error`). All other statuses are terminal — retrying will not fix
|
|
94
|
+
a bad token or a bad payload.
|
|
95
|
+
|
|
96
|
+
## Contract DSL (`Contractful::Contract`)
|
|
97
|
+
|
|
98
|
+
Class-level macros (on the client class):
|
|
99
|
+
|
|
100
|
+
| Macro | Meaning |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| `base(url)` | Absolute http(s) base URL; trailing slashes stripped |
|
|
103
|
+
| `default_headers(hash)` | Merged down the ancestor chain (reader form with no args) |
|
|
104
|
+
| `strict_params(flag)` | Strict unknown-param rejection (default on) |
|
|
105
|
+
| `payload_style(:json \| :form)` | Class default payload routing |
|
|
106
|
+
| `auth bearer: / api_key: / basic:` | Scheme declaration; values may be callables, invoked per request; `api_key:` accepts an array for dual-header schemes and `in: :query` |
|
|
107
|
+
| `idempotency_header(name)`, `idempotency_generator(callable)` | Key header customization |
|
|
108
|
+
| `before_request { \|ctx\| }` | Mutable context: `definition:, method:, url:, headers:, payload:, query:, cookies:` |
|
|
109
|
+
| `after_response { \|resp\| }` | Observe validated responses |
|
|
110
|
+
| `resource :posts, path:, only:, except:, update_with:, singular:` | Generates the five CRUD contracts (non-strict) |
|
|
111
|
+
| `contract :name, 'VERB /path' do ... end` | Declare one operation |
|
|
112
|
+
|
|
113
|
+
Inside a contract block:
|
|
114
|
+
|
|
115
|
+
| Declaration | Meaning |
|
|
116
|
+
| --- | --- |
|
|
117
|
+
| `param :name, Type, required:, default:, inclusion:, min:, max:, length:, pattern:, coerce:, description:, header:, cookie:` | Closed-schema param (String, Integer, Float, `:boolean`, Array, Hash, any class, any Proc). `header:` / `cookie:` send the value as that request header or cookie instead of the query or payload; they take a scalar type only and cannot be a path placeholder |
|
|
118
|
+
| `responds 200, (200..299), type: Array/:hash/:json/...` | Expected statuses + body shape; declaring 4xx/5xx converts them to returned values and judges everything by the contract |
|
|
119
|
+
| `response_field :name, type, required:, strict:` | Open-schema response binding: required+type bind; undeclared fields are data |
|
|
120
|
+
| `verify_response { \|resp, parsed\| }` | Custom assertion; falsey raises `UnexpectedResponse` |
|
|
121
|
+
| `paginated style: :cursor, cursor_param:, next_cursor_path:, items_path:` / `style: :offset, offset_param:, limit_param:, has_more_path:` | Pagination strategy |
|
|
122
|
+
| `idempotent true` | Inject a stable idempotency key header |
|
|
123
|
+
| `auth false` | Opt out of class auth |
|
|
124
|
+
| `payload_style`, `strict_params` | Per-contract overrides |
|
|
125
|
+
|
|
126
|
+
Per-call meta options: `_headers`, `_timeout`, `_open_timeout`,
|
|
127
|
+
`_read_timeout`, `_write_timeout`, `_persistent`, `_max_retries`,
|
|
128
|
+
`_retry_interval`, `_idempotency_key`, `_max_pages`.
|
|
129
|
+
|
|
130
|
+
Generated per contract `:name`: `name(**params)`, `name_url(**params)`, and
|
|
131
|
+
for paginated contracts `name_pages(**params)` (lazy Enumerator of validated
|
|
132
|
+
pages) and `all_name(**params)` (flat collector). Reflection:
|
|
133
|
+
`contracts`, `contract_names`, `contract?`, `contract_for`,
|
|
134
|
+
`Definition#describe`; dynamic dispatch conveniences `call_*`, `*_contract`,
|
|
135
|
+
`has_*?` with `respond_to_missing?` support. Instance-level overrides:
|
|
136
|
+
`Client.new(base:, headers:)`.
|
|
137
|
+
|
|
138
|
+
Contract errors, all rooted at `Contractful::Contract::Error`:
|
|
139
|
+
`InvalidDefinition` (declaration time), `MissingBaseUrl`, `MissingParam`,
|
|
140
|
+
`UnknownParam`, `InvalidParam` (pre-flight), `UnexpectedResponse`
|
|
141
|
+
(`#response` attached; response-contract violations), `PaginationError`
|
|
142
|
+
(missing stop condition / `_max_pages` exceeded).
|
data/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# ARCHITECTURE — System architecture
|
|
2
|
+
|
|
3
|
+
contractful is a layered Ruby library with a deliberately thin core: one
|
|
4
|
+
request pipeline used by every entry point, a transport that is Net::HTTP,
|
|
5
|
+
and a metaprogrammed contract layer that compiles declarations into real
|
|
6
|
+
methods on top of that pipeline. There is no runtime, no daemon, no external
|
|
7
|
+
service dependency — the gem is loaded into the host process and makes HTTP
|
|
8
|
+
calls on demand.
|
|
9
|
+
|
|
10
|
+
## Layer diagram
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
┌────────────────────────────────────────────────────────────┐
|
|
14
|
+
│ Contract layer — Contractful::Contract │
|
|
15
|
+
│ DSL macros → Definition → Executor → define_method │
|
|
16
|
+
│ typed params · response contracts · auth · idempotency │
|
|
17
|
+
│ pagination · rate-limit · callbacks · reflection │
|
|
18
|
+
├────────────────────────────────────────────────────────────┤
|
|
19
|
+
│ High-level API — Contractful.get/post/... · Resource │
|
|
20
|
+
├────────────────────────────────────────────────────────────┤
|
|
21
|
+
│ Request pipeline — Contractful::Request │
|
|
22
|
+
│ payload normalization (Payload, ParamsArray) │
|
|
23
|
+
│ auth (user/password, netrc) · cookies · redirects │
|
|
24
|
+
│ retries + backoff · Retry-After · connection pool │
|
|
25
|
+
├────────────────────────────────────────────────────────────┤
|
|
26
|
+
│ Transport — Net::HTTP + OpenSSL │
|
|
27
|
+
│ ssl_min/max_version normalization · timeouts │
|
|
28
|
+
├────────────────────────────────────────────────────────────┤
|
|
29
|
+
│ Response side — AbstractResponse · Response · RawResponse │
|
|
30
|
+
│ headers · history · #json · RateLimit parsing │
|
|
31
|
+
├────────────────────────────────────────────────────────────┤
|
|
32
|
+
│ Errors — Contractful::Exception hierarchy │
|
|
33
|
+
│ Contractful::Contract::Error hierarchy │
|
|
34
|
+
└────────────────────────────────────────────────────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Module map
|
|
38
|
+
|
|
39
|
+
| Module | Responsibility |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `lib/contractful.rb` | Facade: module-level verb methods, `Contractful.log`, version |
|
|
42
|
+
| `request.rb` | The pipeline: option validation, payload/params prep, transmission, redirects, retries, timeouts, SSL setup |
|
|
43
|
+
| `payload.rb` | Payload normalization: form, JSON, raw, multipart, streaming; `rewind` for retries |
|
|
44
|
+
| `params_array.rb` | Ordered param lists with repeated keys and nested notation |
|
|
45
|
+
| `resource.rb` | ActiveResource-style wrapper around `Request` |
|
|
46
|
+
| `abstract_response.rb` | Shared response behavior: headers, code, cookies, history |
|
|
47
|
+
| `response.rb` | Concrete String-like response body with `.json`, `.rate_limit` |
|
|
48
|
+
| `raw_response.rb` | File-backed response for streaming downloads |
|
|
49
|
+
| `connection_pool.rb` | Thread-safe keep-alive pool (`persistent: true`) |
|
|
50
|
+
| `rate_limit.rb` | IETF `RateLimit-*` / legacy `X-RateLimit-*` parsing |
|
|
51
|
+
| `exceptions.rb` | Status→exception map, `RETRIABLE_STATUSES`, `Exceptions.retryable?` |
|
|
52
|
+
| `contract.rb` | Contract error hierarchy + the `include` hook wiring the DSL |
|
|
53
|
+
| `contract/dsl.rb` | Class macros (`base`, `contract`, `resource`, `auth`, ...), `define_method` generation, reflection |
|
|
54
|
+
| `contract/definition.rb` | One operation: params, responses, path expansion |
|
|
55
|
+
| `contract/param.rb` | Typed param: coercion + closed-schema constraints (`min/max/length/pattern/inclusion`) |
|
|
56
|
+
| `contract/response_field.rb` | Open-schema response field bindings |
|
|
57
|
+
| `contract/auth.rb` | `bearer:` / `api_key:` / `basic:` resolution to headers |
|
|
58
|
+
| `contract/pagination.rb` | Cursor/offset iteration + `PaginationError` guard |
|
|
59
|
+
| `contract/executor.rb` | Per-call execution: validate → build → send → verify → callbacks |
|
|
60
|
+
| `contract/config.rb` | Per-class config objects + ancestor-chain merging |
|
|
61
|
+
| `windows/root_certs.rb` | Windows certificate store loading (separate platform gem) |
|
|
62
|
+
|
|
63
|
+
## Request lifecycle
|
|
64
|
+
|
|
65
|
+
1. **Entry.** A call arrives: `Contractful.get`, `Resource#get`, or a
|
|
66
|
+
generated contract method (`Contract::Executor.call`).
|
|
67
|
+
2. **Contract validation (contract path only).** Params are coerced and
|
|
68
|
+
checked against the `Definition` — required, type, `inclusion:`,
|
|
69
|
+
`min/max/length/pattern`, strict unknown-param rejection. Any violation
|
|
70
|
+
raises (`MissingParam`/`UnknownParam`/`InvalidParam`) **before** the
|
|
71
|
+
network is touched. Path placeholders are expanded and URI-escaped;
|
|
72
|
+
remaining params are routed to query string or JSON/form payload by verb
|
|
73
|
+
and `payload_style`.
|
|
74
|
+
3. **Request assembly.** `Request` validates options, normalizes the payload
|
|
75
|
+
(`Payload::Base` family), merges headers, resolves auth (contract auth
|
|
76
|
+
first, then `before_request` callbacks may adjust everything through the
|
|
77
|
+
mutable context), loads netrc credentials, and applies cookies.
|
|
78
|
+
4. **Connection.** With `persistent: true` the request checks a connection
|
|
79
|
+
out of `Contractful::ConnectionPool` (keyed by host/port/proxy/SSL); the
|
|
80
|
+
key must include the client-certificate fingerprint so credentials never
|
|
81
|
+
leak across pool entries. Otherwise a fresh `Net::HTTP` is configured:
|
|
82
|
+
SSL versions normalized via `normalize_ssl_version`, timeouts applied
|
|
83
|
+
(`open/read/write`), proxy resolved from options or ENV.
|
|
84
|
+
5. **Transmission with retries.** The request transmits; on a retryable
|
|
85
|
+
network failure (`Timeout`, `ECONNRESET`, `EPIPE`, ...) or a retryable
|
|
86
|
+
HTTP status (408, 425, 429, 500, 502, 503, 504) and `:max_retries > 0`,
|
|
87
|
+
it waits — honoring `Retry-After` (delta or HTTP-date, capped by
|
|
88
|
+
`:max_retry_after`) or exponential backoff — rewinds the payload and
|
|
89
|
+
retries with any idempotency key kept stable.
|
|
90
|
+
6. **Response validation.** Classic path: non-2xx raises the mapped
|
|
91
|
+
exception (`Contractful::NotFound`, ...) with the response attached.
|
|
92
|
+
Contract path: the status must be in the declared set, the body must
|
|
93
|
+
satisfy the declared type and `response_field` bindings, and any
|
|
94
|
+
`verify_response` block must pass — otherwise
|
|
95
|
+
`Contract::UnexpectedResponse` (with the response attached). Declared
|
|
96
|
+
error statuses are returned as values instead of raised (redirects still
|
|
97
|
+
followed); contracts without declarations keep classic behavior.
|
|
98
|
+
7. **Delivery.** `after_response` callbacks observe the validated response;
|
|
99
|
+
rate-limit headers are parsed onto `response.rate_limit`; the connection
|
|
100
|
+
is checked back in; the response (or collected page) returns to the
|
|
101
|
+
caller.
|
|
102
|
+
|
|
103
|
+
## Deliberate architecture decisions
|
|
104
|
+
|
|
105
|
+
- **Net::HTTP is the only transport.** No pluggable transport abstraction
|
|
106
|
+
exists today; the per-request meta options (`_persistent`, `_timeout`,
|
|
107
|
+
...) and SSL normalization are typed against what Net::HTTP actually
|
|
108
|
+
supports. This keeps the surface honest — see ADR
|
|
109
|
+
[0002](adr/0002-contract-first-client-layer.md) for why the contract layer
|
|
110
|
+
also avoids a schema-engine dependency.
|
|
111
|
+
- **Generated methods are real methods.** Contract execution is compiled
|
|
112
|
+
with `define_method` at declaration time — `method_missing` handles only
|
|
113
|
+
the convenience families (`call_*`, `*_contract`, `has_*?`) with
|
|
114
|
+
`respond_to_missing?` support. See ADR
|
|
115
|
+
[0003](adr/0003-metaprogrammed-client-generation.md).
|
|
116
|
+
- **One global mutable, thread-safe resource:** the default connection pool.
|
|
117
|
+
Everything else is per-request or per-client-class state.
|
|
118
|
+
- **`frozen_string_literal: true` everywhere**; request/response objects
|
|
119
|
+
never mutate caller-supplied option hashes.
|
|
120
|
+
|
|
121
|
+
## Development-time architecture
|
|
122
|
+
|
|
123
|
+
- **Tests:** RSpec, WebMock for offline integration; contract specs mirror
|
|
124
|
+
the DSL surface under `spec/unit/contract/`; a small live suite against
|
|
125
|
+
httpbin.org runs in CI (see
|
|
126
|
+
[docs/engineering/TESTING.md](docs/engineering/TESTING.md)).
|
|
127
|
+
- **CI:** GitHub Actions matrix Ruby 3.0→4.0 + experimental `ruby-head`,
|
|
128
|
+
`permissions: contents: read`
|
|
129
|
+
([.github/workflows/ci.yml](.github/workflows/ci.yml)).
|
|
130
|
+
- **Packaging:** two gemspecs from one source — the Ruby platform gem and
|
|
131
|
+
the Windows gem (`ffi`-based root certificate store, `x64-mingw-ucrt`).
|
|
132
|
+
|
|
133
|
+
The security architecture — trust boundaries, TLS posture, threat model —
|
|
134
|
+
lives in [docs/security/THREAT_MODEL.md](docs/security/THREAT_MODEL.md).
|
data/AUTHORS
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
The Ruby REST Client would not be what it is today without the help of
|
|
2
|
+
the following kind souls:
|
|
3
|
+
|
|
4
|
+
Adam Jacob
|
|
5
|
+
Adam Wiggins
|
|
6
|
+
Adrian Rangel
|
|
7
|
+
Alex Tomlins
|
|
8
|
+
Aman Gupta
|
|
9
|
+
Andy Brody
|
|
10
|
+
Avi Deitcher
|
|
11
|
+
Blake Mizerany
|
|
12
|
+
Brad Ediger
|
|
13
|
+
Braintree
|
|
14
|
+
Brian Donovan
|
|
15
|
+
Caleb Land
|
|
16
|
+
Chris Dinn
|
|
17
|
+
Chris Frohoff
|
|
18
|
+
Chris Green
|
|
19
|
+
Coda Hale
|
|
20
|
+
Crawford
|
|
21
|
+
Cyril Rohr
|
|
22
|
+
Dan Mayer
|
|
23
|
+
Dario Hamidi
|
|
24
|
+
Darren Coxall
|
|
25
|
+
David Backeus
|
|
26
|
+
David Perkowski
|
|
27
|
+
Dmitri Dolguikh
|
|
28
|
+
Dusty Doris
|
|
29
|
+
Dylan Egan
|
|
30
|
+
El Draper
|
|
31
|
+
Evan Broder
|
|
32
|
+
Evan Smith
|
|
33
|
+
François Beausoleil
|
|
34
|
+
Gabriele Cirulli
|
|
35
|
+
Garry Shutler
|
|
36
|
+
Giovanni Cappellotto
|
|
37
|
+
Greg Borenstein
|
|
38
|
+
Harm Aarts
|
|
39
|
+
Hiro Asari
|
|
40
|
+
Hugh McGowan
|
|
41
|
+
Ian Warshak
|
|
42
|
+
Igor Zubkov
|
|
43
|
+
Ivan Makfinsky
|
|
44
|
+
JH. Chabran
|
|
45
|
+
James Edward Gray II
|
|
46
|
+
Jari Bakken
|
|
47
|
+
Jeff Pereira
|
|
48
|
+
Jeff Remer
|
|
49
|
+
Jeffrey Hardy
|
|
50
|
+
Jeremy Kemper
|
|
51
|
+
Joe Rafaniello
|
|
52
|
+
John Barnette
|
|
53
|
+
Jon Rowe
|
|
54
|
+
Jordi Massaguer Pla
|
|
55
|
+
Joshua J. Campoverde
|
|
56
|
+
Juan Alvarez
|
|
57
|
+
Julien Kirch
|
|
58
|
+
Jun Aruga
|
|
59
|
+
Justin Coyne
|
|
60
|
+
Justin Lambert
|
|
61
|
+
Keith Rarick
|
|
62
|
+
Kenichi Kamiya
|
|
63
|
+
Kevin Read
|
|
64
|
+
Kosuke Asami
|
|
65
|
+
Kyle Meyer
|
|
66
|
+
Kyle VanderBeek
|
|
67
|
+
Lars Gierth
|
|
68
|
+
Lawrence Leonard Gilbert
|
|
69
|
+
Lee Jarvis
|
|
70
|
+
Lennon Day-Reynolds
|
|
71
|
+
Lin Jen-Shin
|
|
72
|
+
Magne Matre Gåsland
|
|
73
|
+
Marc-André Cournoyer
|
|
74
|
+
Marius Butuc
|
|
75
|
+
Matthew Manning
|
|
76
|
+
Michael Klett
|
|
77
|
+
Michael Rykov
|
|
78
|
+
Michael Westbom
|
|
79
|
+
Mike Fletcher
|
|
80
|
+
Nelson Elhage
|
|
81
|
+
Nicholas Wieland
|
|
82
|
+
Nick Hammond
|
|
83
|
+
Nick Plante
|
|
84
|
+
Niko Dittmann
|
|
85
|
+
Nikolay Shebanov
|
|
86
|
+
Oscar Del Ben
|
|
87
|
+
Pablo Astigarraga
|
|
88
|
+
Paul Dlug
|
|
89
|
+
Pedro Belo
|
|
90
|
+
Pedro Chambino
|
|
91
|
+
Philip Corliss
|
|
92
|
+
Pierre-Louis Gottfrois
|
|
93
|
+
Rafael Ssouza
|
|
94
|
+
Richard Schneeman
|
|
95
|
+
Rick Olson
|
|
96
|
+
Robert Eanes
|
|
97
|
+
Rodrigo Panachi
|
|
98
|
+
Sam Norbury
|
|
99
|
+
Samuel Cochran
|
|
100
|
+
Syl Turner
|
|
101
|
+
T. Watanabe
|
|
102
|
+
Tekin
|
|
103
|
+
W. Andrew Loe III
|
|
104
|
+
Waynn Lue
|
|
105
|
+
Xavier Shay
|
|
106
|
+
tpresa
|
data/CODE_OF_CONDUCT.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
|
10
|
+
orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
* Demonstrating empathy and kindness toward other people
|
|
21
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
* Giving and gracefully accepting constructive feedback
|
|
23
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
* Focusing on what is best not just for us as individuals, but for the overall
|
|
26
|
+
community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
* The use of sexualized language or imagery, and sexual attention or advances of
|
|
31
|
+
any kind
|
|
32
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
* Public or private harassment
|
|
34
|
+
* Publishing others' private information, such as a physical or email address,
|
|
35
|
+
without their explicit permission
|
|
36
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement Responsibilities
|
|
40
|
+
|
|
41
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
42
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
43
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
44
|
+
or harmful.
|
|
45
|
+
|
|
46
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
|
47
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
48
|
+
not aligned to this Code of Conduct, and will communicate reasons for
|
|
49
|
+
moderation decisions when appropriate.
|
|
50
|
+
|
|
51
|
+
## Scope
|
|
52
|
+
|
|
53
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
54
|
+
an individual is officially representing the community in public spaces.
|
|
55
|
+
Examples of representing our community include using an official e-mail address,
|
|
56
|
+
posting via an official social media account, or acting as an appointed
|
|
57
|
+
representative at an online or offline event.
|
|
58
|
+
|
|
59
|
+
## Enforcement
|
|
60
|
+
|
|
61
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
|
+
reported to the community leaders responsible for enforcement through
|
|
63
|
+
[GitHub's report content interface](https://docs.github.com/en/communities/moderating-comments-and-conversations/managing-reports-in-your-repository)
|
|
64
|
+
on this repository. All complaints will be reviewed and investigated promptly
|
|
65
|
+
and fairly.
|
|
66
|
+
|
|
67
|
+
All community leaders are obligated to respect the privacy and security of the
|
|
68
|
+
reporter of any incident.
|
|
69
|
+
|
|
70
|
+
## Enforcement Guidelines
|
|
71
|
+
|
|
72
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
|
73
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
|
74
|
+
|
|
75
|
+
### 1. Correction
|
|
76
|
+
|
|
77
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
78
|
+
unprofessional or unwelcome in the community.
|
|
79
|
+
|
|
80
|
+
**Consequence**: A private, written warning from community leaders, providing
|
|
81
|
+
clarity around the nature of the violation and an explanation of why the
|
|
82
|
+
behavior was inappropriate. A public apology may be requested.
|
|
83
|
+
|
|
84
|
+
### 2. Warning
|
|
85
|
+
|
|
86
|
+
**Community Impact**: A violation through a single incident or series of
|
|
87
|
+
actions.
|
|
88
|
+
|
|
89
|
+
**Consequence**: A warning with consequences for continued behavior. No
|
|
90
|
+
interaction with the people involved, including unsolicited interaction with
|
|
91
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
|
92
|
+
includes avoiding interactions in community spaces as well as external channels
|
|
93
|
+
like social media. Violating these terms may lead to a temporary or permanent
|
|
94
|
+
ban.
|
|
95
|
+
|
|
96
|
+
### 3. Temporary Ban
|
|
97
|
+
|
|
98
|
+
**Community Impact**: A serious violation of community standards, including
|
|
99
|
+
sustained inappropriate behavior.
|
|
100
|
+
|
|
101
|
+
**Consequence**: A temporary ban from any sort of interaction or public
|
|
102
|
+
communication with the community for a specified period of time. No public or
|
|
103
|
+
private interaction with the people involved, including unsolicited interaction
|
|
104
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
|
105
|
+
Violating these terms may lead to a permanent ban.
|
|
106
|
+
|
|
107
|
+
### 4. Permanent Ban
|
|
108
|
+
|
|
109
|
+
**Community Impact**: Demonstrating a pattern of violation of community
|
|
110
|
+
standards, including sustained inappropriate behavior, harassment of an
|
|
111
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
|
112
|
+
|
|
113
|
+
**Consequence**: A permanent ban from any sort of public interaction within the
|
|
114
|
+
community.
|
|
115
|
+
|
|
116
|
+
## Attribution
|
|
117
|
+
|
|
118
|
+
This Code of Conduct is adapted from the
|
|
119
|
+
[Contributor Covenant](https://www.contributor-covenant.org), version 2.1,
|
|
120
|
+
available at
|
|
121
|
+
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
|
122
|
+
|
|
123
|
+
Community Impact Guidelines were inspired by
|
|
124
|
+
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
|
|
125
|
+
|
|
126
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
|
127
|
+
https://www.contributor-covenant.org/faq. Translations are available at
|
|
128
|
+
https://www.contributor-covenant.org/translations.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2008-2014 Rest Client Authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|