or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdasync-requests.mdexceptions.mdindex.mdmodels.mdsessions.mdsync-requests.md

models.mddocs/

0

# Request and Response Models

1

2

Core data structures for representing HTTP requests and responses. These classes provide access to all HTTP components including headers, body content, status codes, and metadata. They form the foundation of all HTTP operations in niquests.

3

4

## Capabilities

5

6

### Request Class

7

8

A user-created Request object used to represent an HTTP request before it's prepared for transmission.

9

10

```python { .api }

11

class Request:

12

"""

13

A user-created Request object.

14

15

Used to prepare a PreparedRequest, which is sent to the server.

16

Contains the high-level request information provided by the user.

17

"""

18

19

def __init__(

20

self,

21

method: HttpMethodType,

22

url: str,

23

*,

24

headers: HeadersType | None = None,

25

files: MultiPartFilesType | MultiPartFilesAltType | None = None,

26

data: BodyType | None = None,

27

json: Any | None = None,

28

params: QueryParameterType | None = None,

29

auth: HttpAuthenticationType | None = None,

30

cookies: CookiesType | None = None,

31

hooks: HookType[PreparedRequest | Response] | None = None,

32

):

33

"""

34

Initialize a new Request object.

35

36

Args:

37

method: HTTP method (GET, POST, PUT, etc.)

38

url: Target URL

39

headers: HTTP headers dictionary

40

files: Files for multipart upload

41

data: Request body data

42

json: JSON data to serialize

43

params: Query parameters

44

auth: Authentication credentials

45

cookies: Cookies to include

46

hooks: Request/response hooks

47

"""

48

49

def prepare(self) -> PreparedRequest:

50

"""

51

Prepare the Request for transmission.

52

53

Returns:

54

PreparedRequest ready for sending

55

"""

56

57

# Instance attributes

58

method: HttpMethodType

59

url: str

60

headers: HeadersType | None

61

files: MultiPartFilesType | MultiPartFilesAltType | None

62

data: BodyType | None

63

json: Any | None

64

params: QueryParameterType | None

65

auth: HttpAuthenticationType | None

66

cookies: CookiesType | None

67

hooks: HookType | None

68

```

69

70

### PreparedRequest Class

71

72

The fully prepared request object containing the exact bytes that will be sent to the server.

73

74

```python { .api }

75

class PreparedRequest:

76

"""

77

The fully mutable PreparedRequest object.

78

79

Contains the exact bytes that will be sent to the server.

80

Generated from a Request object and should not be instantiated manually.

81

"""

82

83

def __init__(self):

84

"""Initialize a new PreparedRequest."""

85

86

def prepare(

87

self,

88

method: HttpMethodType | None = None,

89

url: str | None = None,

90

files: MultiPartFilesType | MultiPartFilesAltType | None = None,

91

data: BodyType | None = None,

92

json: Any | None = None,

93

headers: HeadersType | None = None,

94

params: QueryParameterType | None = None,

95

auth: HttpAuthenticationType | None = None,

96

cookies: CookiesType | None = None,

97

hooks: HookType[PreparedRequest | Response] | None = None,

98

):

99

"""

100

Prepare all aspects of the request.

101

102

Args:

103

method: HTTP method

104

url: Target URL

105

files: Files for upload

106

data: Request body

107

json: JSON data

108

headers: HTTP headers

109

params: Query parameters

110

auth: Authentication

111

cookies: Cookies

112

hooks: Lifecycle hooks

113

"""

114

115

def copy(self) -> PreparedRequest:

116

"""

117

Copy the PreparedRequest.

118

119

Returns:

120

New PreparedRequest instance with same data

121

"""

122

123

# Instance attributes

124

method: HttpMethodType | None

125

url: str | None

126

headers: HeadersType | None

127

body: bytes | None

128

hooks: HookType | None

129

path_url: str | None

130

```

131

132

### Response Class

133

134

The Response object containing a server's response to an HTTP request.

135

136

```python { .api }

137

class Response:

138

"""

139

The Response object containing a server's response to an HTTP request.

140

141

Provides access to response data, headers, status code, and metadata.

142

"""

143

144

def __init__(self):

145

"""Initialize a new Response object."""

146

147

def __enter__(self) -> Response:

148

"""Enter context manager for response."""

149

return self

150

151

def __exit__(self, *args):

152

"""Exit context manager and close response."""

153

self.close()

154

155

@property

156

def content(self) -> bytes:

157

"""

158

Content of the response, in bytes.

159

160

Returns:

161

Response body as bytes

162

"""

163

164

@property

165

def text(self) -> str:

166

"""

167

Content of the response, in unicode.

168

169

If Response.encoding is None, encoding will be guessed using

170

charset-normalizer or chardet.

171

172

Returns:

173

Response body as string

174

"""

175

176

@property

177

def encoding(self) -> str | None:

178

"""

179

Encoding to decode with when accessing text.

180

181

Returns:

182

Character encoding name or None

183

"""

184

185

@encoding.setter

186

def encoding(self, value: str):

187

"""Set the encoding for text decoding."""

188

189

def json(self, **kwargs) -> Any:

190

"""

191

Return the json-encoded content of a response, if any.

192

193

Args:

194

**kwargs: Optional arguments to pass to json.loads()

195

196

Returns:

197

JSON-decoded response content

198

199

Raises:

200

JSONDecodeError: If response content is not valid JSON

201

"""

202

203

@property

204

def links(self) -> dict:

205

"""

206

Returns the parsed header links of the response, if any.

207

208

Returns:

209

Dictionary of link relations to links

210

"""

211

212

@property

213

def ok(self) -> bool:

214

"""

215

Returns True if status_code is less than 400, False otherwise.

216

217

Returns:

218

True for successful responses (status < 400)

219

"""

220

221

@property

222

def is_redirect(self) -> bool:

223

"""

224

True if this Response is a well-formed HTTP redirect.

225

226

Returns:

227

True if response is a redirect

228

"""

229

230

@property

231

def is_permanent_redirect(self) -> bool:

232

"""

233

True if this Response is a permanent redirect.

234

235

Returns:

236

True if response is a permanent redirect (301, 308)

237

"""

238

239

def iter_content(self, chunk_size: int = 1, decode_unicode: bool = False):

240

"""

241

Iterate over the response data in chunks.

242

243

Args:

244

chunk_size: Size of each chunk in bytes

245

decode_unicode: Whether to decode chunks to unicode

246

247

Yields:

248

Raw bytes or decoded strings if decode_unicode=True

249

"""

250

251

def iter_lines(self, chunk_size: int = 512, decode_unicode: bool = False, delimiter: str | None = None):

252

"""

253

Iterate over the response data one line at a time.

254

255

Args:

256

chunk_size: Size of chunks to read

257

decode_unicode: Whether to decode lines to unicode

258

delimiter: Line delimiter to use

259

260

Yields:

261

Lines from the response content

262

"""

263

264

def raise_for_status(self):

265

"""

266

Raise HTTPError if one occurred.

267

268

Raises:

269

HTTPError: If the response status indicates an error

270

"""

271

272

def close(self):

273

"""

274

Release the connection back to the pool.

275

276

Once this method has been called the underlying raw object

277

must not be accessed again.

278

"""

279

280

# Instance attributes

281

status_code: int # HTTP status code

282

headers: HeadersType # Response headers

283

raw: BaseHTTPResponse | None # Raw response object

284

url: str # Final URL after redirects

285

encoding: str | None # Character encoding

286

history: list[Response] # List of redirect responses

287

reason: str # HTTP status reason phrase

288

cookies: RequestsCookieJar # Response cookies

289

elapsed: datetime.timedelta # Time taken for request

290

request: PreparedRequest # The request that generated this response

291

connection: ConnectionInfo # Connection information

292

extensions: dict # Protocol extensions (WebSocket, etc.)

293

```

294

295

### AsyncResponse Class

296

297

Async version of the Response class for asynchronous HTTP operations.

298

299

```python { .api }

300

class AsyncResponse(Response):

301

"""

302

The AsyncResponse object for asynchronous HTTP requests.

303

304

Inherits from Response and provides async methods for content access.

305

"""

306

307

async def aclose(self):

308

"""

309

Asynchronously release the connection back to the pool.

310

"""

311

312

def close(self):

313

"""

314

Synchronously close the response (calls aclose internally).

315

"""

316

317

async def json(self, **kwargs) -> Any:

318

"""

319

Asynchronously return the json-encoded content of the response.

320

321

Args:

322

**kwargs: Optional arguments to pass to json.loads()

323

324

Returns:

325

JSON-decoded response content

326

327

Raises:

328

JSONDecodeError: If response content is not valid JSON

329

"""

330

331

@property

332

async def content(self) -> bytes:

333

"""

334

Asynchronously access content of the response, in bytes.

335

336

Returns:

337

Response body as bytes

338

"""

339

340

@property

341

async def text(self) -> str:

342

"""

343

Asynchronously access content of the response, in unicode.

344

345

Returns:

346

Response body as string

347

"""

348

349

# Async context manager support

350

async def __aenter__(self) -> AsyncResponse:

351

"""Enter async context manager."""

352

return self

353

354

async def __aexit__(self, *args):

355

"""Exit async context manager and close response."""

356

await self.aclose()

357

```

358

359

## Usage Examples

360

361

### Creating and Using Requests

362

363

```python

364

import niquests

365

366

# Create a Request object

367

request = niquests.Request(

368

method='POST',

369

url='https://api.example.com/users',

370

json={'name': 'John Doe', 'email': 'john@example.com'},

371

headers={'Content-Type': 'application/json'}

372

)

373

374

# Prepare the request

375

prepared = request.prepare()

376

377

# Send using a session

378

with niquests.Session() as session:

379

response = session.send(prepared)

380

print(response.status_code)

381

```

382

383

### Working with Responses

384

385

```python

386

import niquests

387

388

# Make a request and get response

389

response = niquests.get('https://api.example.com/users')

390

391

# Access response properties

392

print(f"Status Code: {response.status_code}")

393

print(f"Status Reason: {response.reason}")

394

print(f"Content Type: {response.headers.get('content-type')}")

395

print(f"Response Size: {len(response.content)} bytes")

396

397

# Check if request was successful

398

if response.status_code == 200:

399

# Parse JSON response

400

users = response.json()

401

print(f"Found {len(users)} users")

402

else:

403

print(f"Request failed: {response.status_code}")

404

405

# Raise exception for HTTP errors

406

try:

407

response.raise_for_status()

408

data = response.json()

409

except niquests.HTTPError as e:

410

print(f"HTTP Error: {e}")

411

except niquests.JSONDecodeError as e:

412

print(f"JSON Decode Error: {e}")

413

```

414

415

### Response Content Handling

416

417

```python

418

# Text content with automatic encoding detection

419

response = niquests.get('https://example.com/page.html')

420

html_content = response.text

421

422

# Binary content

423

response = niquests.get('https://example.com/image.jpg')

424

image_bytes = response.content

425

426

# Save binary content to file

427

with open('downloaded_image.jpg', 'wb') as f:

428

f.write(response.content)

429

430

# Streaming large responses

431

response = niquests.get('https://example.com/large-file.zip', stream=True)

432

with open('large-file.zip', 'wb') as f:

433

for chunk in response.iter_content(chunk_size=8192):

434

f.write(chunk)

435

```

436

437

### Async Response Handling

438

439

```python

440

import asyncio

441

import niquests

442

443

async def fetch_and_process():

444

response = await niquests.aget('https://api.example.com/data')

445

446

# Async context manager automatically closes response

447

async with response:

448

# Async content access

449

json_data = await response.json()

450

text_content = await response.text

451

binary_content = await response.content

452

453

return json_data

454

455

# Run async function

456

data = asyncio.run(fetch_and_process())

457

```

458

459

### Response Metadata

460

461

```python

462

response = niquests.get('https://httpbin.org/get')

463

464

# Connection information

465

print(f"HTTP Version: {response.connection.http_version}")

466

print(f"Remote Address: {response.connection.destination_address}")

467

468

# Timing information

469

print(f"Request took: {response.elapsed.total_seconds()} seconds")

470

471

# Redirect history

472

if response.history:

473

print(f"Request was redirected {len(response.history)} times")

474

for i, redirect in enumerate(response.history):

475

print(f" Redirect {i+1}: {redirect.status_code} -> {redirect.url}")

476

477

# Cookie handling

478

if response.cookies:

479

print("Response cookies:")

480

for cookie in response.cookies:

481

print(f" {cookie.name}: {cookie.value}")

482

483

# Link headers (for pagination, etc.)

484

if response.links:

485

print("Link headers:")

486

for rel, link in response.links.items():

487

print(f" {rel}: {link['url']}")

488

```

489

490

### Error Handling with Models

491

492

```python

493

import niquests

494

495

try:

496

response = niquests.get('https://api.example.com/protected', timeout=5.0)

497

response.raise_for_status() # Raise HTTPError for bad status codes

498

499

data = response.json()

500

print("Success:", data)

501

502

except niquests.ConnectionError:

503

print("Failed to connect to the server")

504

except niquests.Timeout:

505

print("Request timed out")

506

except niquests.HTTPError as e:

507

print(f"HTTP error {e.response.status_code}: {e.response.reason}")

508

# Can still access response data even for errors

509

if e.response.headers.get('content-type') == 'application/json':

510

error_details = e.response.json()

511

print(f"Error details: {error_details}")

512

except niquests.JSONDecodeError:

513

print("Response is not valid JSON")

514

print("Raw content:", response.text)

515

```

516

517

## Advanced Features

518

519

### Custom Response Processing

520

521

```python

522

class CustomResponse(niquests.Response):

523

"""Custom response class with additional methods."""

524

525

def is_json(self) -> bool:

526

"""Check if response content type is JSON."""

527

content_type = self.headers.get('content-type', '')

528

return 'application/json' in content_type.lower()

529

530

def safe_json(self, default=None):

531

"""Safely parse JSON, returning default if parsing fails."""

532

if self.is_json():

533

try:

534

return self.json()

535

except niquests.JSONDecodeError:

536

pass

537

return default

538

539

# Note: Custom response classes would need to be used with custom adapters

540

```

541

542

### Response Streaming

543

544

```python

545

def download_large_file(url, filename):

546

"""Download large file with progress tracking."""

547

response = niquests.get(url, stream=True)

548

response.raise_for_status()

549

550

total_size = int(response.headers.get('content-length', 0))

551

downloaded = 0

552

553

with open(filename, 'wb') as f:

554

for chunk in response.iter_content(chunk_size=8192):

555

if chunk: # Filter out keep-alive chunks

556

f.write(chunk)

557

downloaded += len(chunk)

558

559

if total_size > 0:

560

progress = (downloaded / total_size) * 100

561

print(f"Downloaded: {progress:.1f}%")

562

563

print(f"Download complete: {filename}")

564

```

565

566

## Type Definitions

567

568

```python { .api }

569

# Base HTTP types

570

HttpMethodType = Literal["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]

571

HeadersType = Union[dict, Headers, CaseInsensitiveDict]

572

CookiesType = Union[dict, RequestsCookieJar]

573

574

# Request body types

575

BodyType = Union[str, bytes, dict, list, IOBase]

576

AsyncBodyType = Union[str, bytes, dict, list, IOBase, AsyncIterable[bytes]]

577

578

# Multipart file types

579

MultiPartFilesType = dict

580

MultiPartFilesAltType = dict

581

582

# Query parameters

583

QueryParameterType = Union[dict, list, bytes]

584

585

# Authentication types

586

HttpAuthenticationType = Union[Tuple[str, str], HTTPBasicAuth, BearerTokenAuth]

587

AsyncHttpAuthenticationType = Union[HttpAuthenticationType, Callable]

588

589

# Hook types

590

HookType = dict

591

592

# Connection info

593

ConnectionInfo = object # Detailed connection metadata

594

```