Skip to content

Commit 99395f9

Browse files
committed
Refactor: Move modules to separate files for better organization
- Extract HTTP.Request, HTTP.Response, HTTP.AbortController, and HTTP.Promise into individual files - Create lib/http/ directory structure for organized code layout - Move corresponding tests to test/http/ directory structure - Update main HTTP module to use separated modules via aliases - Maintain full backward compatibility and all existing functionality - All 30 tests continue to pass Files restructured: - lib/http/request.ex (from HTTP.Request in lib/http.ex) - lib/http/response.ex (from HTTP.Response in lib/http.ex) - lib/http/abort_controller.ex (from HTTP.AbortController in lib/http.ex) - lib/http/promise.ex (from HTTP.Promise in lib/http.ex) - test/http/request_test.exs - test/http/response_test.exs - test/http/abort_controller_test.exs - test/http/promise_test.exs - Updated test/http_test.exs to focus on integration tests
1 parent 516afaf commit 99395f9

16 files changed

+1018
-0
lines changed

.formatter.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Used by "mix format"
2+
[
3+
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
4+
]

.gitignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# The directory Mix will write compiled artifacts to.
2+
/_build/
3+
4+
# If you run "mix test --cover", coverage assets end up here.
5+
/cover/
6+
7+
# The directory Mix downloads your dependencies sources to.
8+
/deps/
9+
10+
# Where third-party dependencies like ExDoc output generated docs.
11+
/doc/
12+
13+
# If the VM crashes, it generates a dump, let's ignore it too.
14+
erl_crash.dump
15+
16+
# Also ignore archive artifacts (built via "mix archive.build").
17+
*.ez
18+
19+
# Ignore package tarball (built via "mix hex.build").
20+
http_fetch-*.tar
21+
22+
# Temporary files, for example, from tests.
23+
/tmp/

CLAUDE.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is an Elixir project that implements a browser-like HTTP fetch API using Erlang's built-in `:httpc` module. It provides a Promise-based asynchronous interface with support for request cancellation via AbortController.
8+
9+
## Key Architecture
10+
11+
The codebase is structured around these core modules:
12+
13+
- **HTTP**: Main module providing the `fetch/2` function and Response struct
14+
- **HTTP.Request**: Struct for building HTTP requests with proper conversion to `:httpc` arguments
15+
- **HTTP.Response**: Struct representing HTTP responses with JSON/text parsing helpers
16+
- **HTTP.AbortController**: Agent-based request cancellation mechanism
17+
- **HTTP.Promise**: Promise-like wrapper around Elixir Tasks for async operations with chaining support
18+
19+
## Development Commands
20+
21+
```bash
22+
# Install dependencies
23+
mix deps.get
24+
25+
# Run tests
26+
mix test
27+
28+
# Run specific test
29+
mix test test/http_test.exs:5
30+
31+
# Interactive development
32+
iex -S mix
33+
34+
# Build the project
35+
mix compile
36+
37+
# Format code
38+
mix format
39+
40+
# Run in production mode
41+
MIX_ENV=prod mix compile
42+
```
43+
44+
## Key Usage Patterns
45+
46+
```elixir
47+
# Basic fetch
48+
promise = HTTP.fetch("https://api.example.com/data")
49+
{:ok, response} = HTTP.Promise.await(promise)
50+
51+
# JSON parsing
52+
case HTTP.Response.json(response) do
53+
{:ok, data} -> handle_data(data)
54+
{:error, reason} -> handle_error(reason)
55+
end
56+
57+
# Promise chaining
58+
HTTP.fetch("https://api.example.com/users")
59+
|> HTTP.Promise.then(&HTTP.Response.json/1)
60+
|> HTTP.Promise.then(fn {:ok, users} -> process_users(users) end)
61+
|> HTTP.Promise.await()
62+
63+
# Request cancellation
64+
controller = HTTP.AbortController.new()
65+
promise = HTTP.fetch("https://slow-api.example.com", signal: controller)
66+
HTTP.AbortController.abort(controller) # Cancel the request
67+
```
68+
69+
## Important Notes
70+
71+
- Requires Elixir 1.18+ for built-in JSON support
72+
- Uses `:inets` and `:httpc` from Erlang's standard library
73+
- All HTTP operations are asynchronous by default (sync: false)
74+
- Request timeout defaults to 120 seconds
75+
- Content-Type defaults to "application/octet-stream" for requests with bodies

0 commit comments

Comments
 (0)