Courseiva

CCNA Networking And Restful Apis Questions

63 questions · Networking And Restful Apis topic · All types, answers revealed

1
Multi-Selecthard

Which THREE of the following are true regarding the use of 'threading' and 'requests' in Python?

Select 3 answers
A.Threads share the same memory space
B.Requests is inherently CPU-bound
C.Using a Session object in every thread is a best practice for persistence
D.Threads bypass the GIL entirely
E.Threading is suitable for I/O-bound tasks like API calls
AnswersA, C, E

Threads within one process share the same heap and global interpreter state, so concurrent requests code can read and mutate common objects directly. This shared memory is precisely why synchronisation primitives such as locks are needed to avoid race conditions.

Why this answer

Option A is correct because threads within a single Python process share the same memory space, which allows them to access shared objects and data directly (though this requires synchronization primitives like locks to avoid race conditions). Option C is correct because creating a requests.Session object per thread is a best practice: a Session provides connection pooling and cookie persistence, and since Session objects are not thread-safe, each thread should have its own instance to avoid cross-thread interference. Option E is correct because threading is well suited for I/O-bound tasks such as API calls with the requests library, since threads release the GIL during blocking I/O operations, allowing other threads to run concurrently.

Option B is incorrect because requests is inherently I/O-bound (network operations), not CPU-bound. Option D is incorrect because threads do not bypass the GIL entirely; the GIL still serializes bytecode execution, and threads only release it during I/O or explicit C-level calls.

2
Multi-Selectmedium

You are consuming a paginated REST API that returns a JSON object with a 'data' list and a 'next' field holding the URL of the following page, or null on the last page. You want a loop that retrieves every record exactly once. Which TWO statements about implementing this loop correctly are true? (Choose two.)

Select 2 answers
A.You should call response.json() once and reuse the parsed object for subsequent pages to save CPU.
B.You must stop the loop when the 'next' field is null, since that signals there are no further pages.
C.You should set verify=False on each request so pagination is not slowed by certificate checks.
D.You should follow the 'next' URL from the response body rather than constructing page numbers yourself, because the API may use opaque cursors.
E.You should assume the 'next' value is always an absolute URL and pass it directly to requests.get without inspection.
AnswersB, D

The contract described in the scenario uses null to mark the final page, so testing for null is the reliable termination condition. Continuing past it would issue a request with no valid target, and stopping earlier would silently drop records, so this check is essential for correctness.

Why this answer

Following the server-provided next link respects opaque pagination tokens, and terminating when that field is null matches the documented contract. Reusing a single parsed body, disabling TLS verification, or assuming next is always absolute all lead to incorrect or fragile behavior, so those statements are not true.

Exam trap

The trap here is treating the next link as a predictable page number and assuming it is always absolute, when it may be a relative path or an opaque cursor.

3
MCQeasy

Which of the following headers is commonly used in REST APIs to indicate the format of the request body?

A.Authorization
B.Accept
C.Content-Type
D.User-Agent
AnswerC

Content-Type declares the media type of the request payload, letting the server select the correct parser. It satisfies the stem's requirement to indicate the request body's format, unlike Accept, which instead negotiates the response representation the client wants returned.

Why this answer

The 'Content-Type' header tells the server what type of media is being sent in the request body.

4
MCQmedium

You are writing a Python client to consume a REST API. The API documentation states that the server may respond with a 307 Temporary Redirect when a resource has moved temporarily. You need to ensure that your client, built with the 'requests' library, preserves the original HTTP method and body when following such redirects. Which of the following best describes how 'requests' handles a 307 redirect by default?

A.It changes the request method to GET and discards the body.
B.It returns the 307 response directly without following the redirect.
C.It raises a 'TooManyRedirects' exception immediately.
D.It automatically re-sends the request with the same method and body to the new URL.
AnswerD

The 'requests' library, via urllib3, follows 307 redirects by re-issuing the request with the original method and body intact. This is in accordance with RFC 7231, which specifies that a 307 response must not change the request method. Therefore, a POST request remains a POST with its original payload when the client follows the redirect.

Why this answer

When 'requests' encounters a 307 Temporary Redirect, it follows the redirect while preserving the original HTTP method and request body, as mandated by the HTTP specification. This ensures that non-idempotent requests like POST are not inadvertently converted to GET, which could lead to data loss or unintended side effects. The library handles this automatically unless redirects are disabled.

Exam trap

The trap here is assuming that all redirects convert POST to GET, which is true for 301 and 302 in some clients but not for 307.

5
MCQmedium

You are writing a Python script that uses the `socket` module to create a TCP client. After calling `sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)`, which method should you call next to initiate a connection to a remote server at `('example.com', 80)`?

A.sock.listen(5)
B.sock.bind(('example.com', 80))
C.sock.accept()
D.sock.connect(('example.com', 80))
AnswerD

`connect()` is the correct method for a client socket to establish a connection to a remote server. It takes a tuple of the remote address and port. This initiates the TCP three-way handshake and prepares the socket for sending and receiving data, exactly as needed in this scenario.

Why this answer

To connect a TCP client socket to a remote server, you must call the `connect()` method with the server's address and port. The other methods are used in server-side socket programming: `bind()` to associate a local address, `listen()` to enable incoming connections, and `accept()` to accept them. Thus, `connect()` is the only correct step for a client.

Exam trap

The trap here is confusing client-side and server-side socket methods, especially thinking `bind()` is needed before connecting on a client.

6
MCQmedium

Which module provides a high-level API for working with URLs, such as parsing and unparsing them?

A.requests
B.urllib.parse
C.socket
D.http.client
AnswerB

urllib.parse supplies urlparse, urlunparse, urljoin and quote, giving a high-level interface for splitting URLs into components and reassembling them. It directly satisfies the stem's parsing and unparsing requirement, whereas urllib.request handles fetching and urllib.error handles exceptions.

Why this answer

The 'urllib.parse' module is designed for splitting and joining URL components.

7
Multi-Selectmedium

Which TWO of the following exceptions might be raised during socket operations?

Select 2 answers
A.ImportError
B.ValueError
C.TimeoutError
D.KeyError
E.ConnectionRefusedError
AnswersC, E

TimeoutError arises from socket operations when a blocking call exceeds its configured timeout, satisfying the stem's requirement for exceptions raised during socket operations. It is raised by methods such as `recv()`, `accept()` and `connect()` after `settimeout()` elapses, making it a genuine socket-related exception rather than an unrelated error.

Why this answer

TimeoutError (option C) is correct because socket operations that use a timeout (e.g., after calling socket.settimeout() or when a connect/recv/send exceeds the configured timeout) raise socket.timeout, which is an alias/subclass of TimeoutError in Python 3.10+. ConnectionRefusedError (option E) is correct because when a client attempts to connect to a host/port where no process is listening, the TCP RST response causes the OS to report ECONNREFUSED, which Python surfaces as ConnectionRefusedError (a subclass of OSError). The other options do not belong: ImportError (A) relates to module import failures, ValueError (B) is a generic value/argument error not specific to socket I/O, and KeyError (D) arises from missing dictionary keys, none of which are raised by socket operations themselves.

8
Multi-Selecteasy

Which TWO of the following represent common data formats used for REST API request/response payloads?

Select 2 answers
A.XML
B.Plain text only
C.SQL queries
E.Binary-encoded images
AnswersA, D

XML is a widely used REST payload format, employing tag-based markup to structure data with attributes and nested elements. It satisfies the stem's requirement for a common REST API data format, alongside JSON. Its verbosity and schema support suit enterprise integrations, though JSON has largely overtaken it for modern lightweight APIs.

Why this answer

XML (A) is correct because REST APIs commonly use it as a structured, self-describing payload format, typically with the Content-Type application/xml or text/xml, and many frameworks support XML serialization/deserialization. JSON (D) is correct because it is the most widely used REST payload format, with Content-Type application/json, offering lightweight key-value and array structures that map easily to objects in most languages. The unmarked options do not belong: plain text only (B) is not a structured data format for typical REST payloads, SQL queries (C) are database commands rather than a payload serialization format, and binary-encoded images (E) are media content, not a common structured data format for REST request/response bodies.

9
MCQmedium

You are writing a client that must upload a binary file to a REST endpoint using requests.put(). The file is several hundred megabytes, and you want to avoid loading it entirely into memory while still letting the server know the total size. Which approach meets both goals?

A.Read the file with open(path, 'rb').read() and pass the resulting bytes to the data argument.
B.Encode the file with base64 and pass the result as a JSON string in the json argument.
C.Pass the file path string directly as the data argument so requests opens it on your behalf.
D.Open the file in binary mode and pass the file object as the data argument, optionally setting the Content-Length header explicitly.
AnswerD

Passing an open binary file object streams the contents to the socket in chunks rather than reading it all at once, keeping memory use low. Setting Content-Length explicitly informs the server of the total size, which is useful when the server requires it or when chunked transfer is undesirable.

Why this answer

Supplying an open binary file object as data lets requests stream the body in chunks, avoiding a full in-memory copy, and an explicit Content-Length header communicates the total size. Reading bytes, passing a path string, or base64-encoding into JSON all either consume large memory or send the wrong payload format.

Exam trap

The trap here is assuming data accepts a filename or that reading the file first is harmless, when the parameter expects content or a stream and full reads defeat streaming.

10
Multi-Selectmedium

Which THREE of the following are attributes of the 'requests.Response' object?

Select 3 answers
A.socket
B.text
C.status_code
D.connect()
E.json()
AnswersB, C, E

The text attribute holds the response body decoded into a string using the charset from the Content-Type header, falling back to apparent encoding. It is a property of requests.Response, distinct from content, which returns undecoded bytes.

Why this answer

Option B (text) is correct because requests.Response.text returns the response body decoded into a Unicode string using the encoding inferred from the HTTP headers or apparent encoding. Option C (status_code) is correct because requests.Response.status_code holds the integer HTTP status code (e.g., 200, 404) returned by the server. Option E (json()) is correct because requests.Response.json() is a method that deserializes the response body from JSON into Python objects (dict/list), raising a JSONDecodeError if parsing fails.

Option A (socket) is not a documented attribute of Response; the underlying socket is managed by urllib3 and accessed via raw/connection internals, not as a direct Response attribute. Option D (connect()) is not a Response method; connect() belongs to HTTPAdapter/urllib3 connection handling, not to the Response object.

11
MCQeasy

A Python script consumes a REST endpoint that returns a JSON document. You call response = requests.get(url) and want to convert the body into native Python objects. The response is guaranteed to be valid JSON. Which expression gives you the deserialized data?

A.response.json()
B.response.content
C.response.text
D.json.load(response)
AnswerA

The json method on a Response decodes the body using the json module and returns the corresponding Python object, such as a dict or list. It is the direct, idiomatic way to deserialize a JSON API response and raises a clear error if the body is not valid JSON.

Why this answer

A requests Response exposes a json method that parses the body with the standard library's JSON decoder and returns native Python types. The text and content attributes expose the body as a string or bytes respectively, and json.load expects a file-like object, so none of those directly yield deserialized data.

Exam trap

The trap here is confusing the raw body accessors text and content with the parsing method json, which is the only one that returns Python objects.

12
MCQeasy

In the 'requests' library, which HTTP method is typically used to update an existing resource on a server?

A.PUT
B.POST
C.GET
D.DELETE
AnswerA

PUT replaces the entire target resource representation at its URI, making it the standard method for full updates. PATCH performs partial modification, while POST typically creates a new subordinate resource rather than updating an existing one.

Why this answer

The PUT method is standard for replacing or updating an existing resource at a specific URI.

13
MCQmedium

What is the purpose of the 'socket.shutdown()' method in Python?

A.It forces the socket to release its memory
B.It resets the socket connection immediately
C.It stops further communication on the socket
D.It closes the file descriptor completely
AnswerC

shutdown() disables further send or receive operations on the socket, optionally in one direction, without closing the file descriptor. This satisfies the stem by halting communication while leaving the socket object itself intact for later close().

Why this answer

shutdown() allows you to stop sending or receiving data on a socket while keeping the file descriptor open.

14
MCQeasy

When receiving data from a TCP socket using 'recv(buffer_size)', what does the returned value represent?

A.A boolean indicating connection status
B.The data as a byte string
C.The total number of bytes in the stream
D.The number of packets received
AnswerB

recv() returns the bytes actually received, up to buffer_size, as a bytes object — not a decoded string, count, or address. This byte-string value is what the caller must decode or process, satisfying the scenario's need to know what the return represents.

Why this answer

The method returns the bytes received, up to the specified buffer size.

15
Multi-Selecthard

Which THREE of the following steps are required to initialize a TCP server socket?

Select 3 answers
A.Create a socket with socket.AF_INET and socket.SOCK_STREAM
B.Call connect() to start the server
C.Call listen() to enable incoming connections
D.Call recv() before bind()
E.Call bind() to associate with an address and port
AnswersA, C, E

Creating the socket with `AF_INET` and `SOCK_STREAM` is the mandatory first step: it allocates an IPv4 TCP endpoint before any binding or listening can occur. Without this stream socket, `bind()` and `listen()` have no file descriptor to operate on, so the server cannot accept connections.

Why this answer

Option A is correct because a TCP server must first create a stream socket using socket.AF_INET for IPv4 addressing and socket.SOCK_STREAM for TCP, which establishes the endpoint that will later be bound and listened on. Option C is correct because after binding, the server must call listen() to put the socket into passive mode so it can accept incoming connection requests, which is what makes it a listening server socket. Option E is correct because bind() associates the socket with a specific local IP address and port, which is required before the socket can listen for connections on that address.

Option B is incorrect because connect() is used by a client to initiate a connection to a server, not by a server to start listening. Option D is incorrect because recv() is used to receive data on an already-connected socket and cannot be called before bind() during server initialization.

Exam trap

PCPP1 often tests whether candidates confuse client-side calls (connect, recv) with server-side initialization steps (socket, bind, listen), catching those who mix up the two roles.

16
MCQmedium

When sending a JSON payload with 'requests.post()', which argument should you use to automatically set the 'Content-Type' to 'application/json'?

A.data=json.dumps(payload)
B.json=payload
C.params=payload
D.body=payload
AnswerB

Passing `json=payload` serialises the dictionary and sets the `Content-Type` header to `application/json` automatically, satisfying the stem's requirement to avoid manual header configuration. The `data=` argument would instead send a form-encoded body, leaving the content type unset or incorrect.

Why this answer

The 'json' argument automatically serializes the data and sets the correct headers.

17
MCQeasy

When using 'requests.get()', how can you include a custom HTTP header in your request?

A.Use the 'data' argument
B.Pass it as part of the URL string
C.Use the 'headers' dictionary argument
D.Use the 'params' dictionary
AnswerC

Passing a dictionary to the `headers` argument lets `requests.get()` merge those key-value pairs into the outgoing HTTP request, satisfying the requirement to send a custom header. Each key becomes a header field name and each value its content, so `requests.get(url, headers={'X-Custom': 'value'})` transmits it directly.

Why this answer

The 'headers' parameter accepts a dictionary of HTTP headers.

18
MCQmedium

You need to send binary data over a socket. Which method should you use on the socket object to ensure all data is sent?

A.write()
B.sendall()
C.send()
D.recv()
AnswerB

`sendall()` loops internally until every byte is handed to the socket buffer, so it satisfies the stem's requirement that all binary data be sent. Unlike `send()`, which may transmit only part of the payload and return a byte count, `sendall()` raises an exception on failure and returns `None`.

Why this answer

The sendall() method continues to transmit data from the buffer until all data has been sent or an error occurs.

19
MCQhard

You are developing a multithreaded HTTP scraper. When using the 'requests' library inside 'threading.Thread' objects, what is the recommended practice for handling session persistence?

A.Initialize a new Session object inside each thread's run method
B.Wrap the session object in a threading.Lock
C.Share a single global Session object across all threads
D.Disable connection pooling using 'pool_connections=0'
AnswerA

A Session is not thread-safe, so sharing one across threads risks corrupted connection-pool state. Creating a Session inside each thread's run method gives every thread its own pool and cookie jar, satisfying the stem's session-persistence requirement without cross-thread contention.

Why this answer

The requests.Session object is not thread-safe because it maintains shared state such as cookies, connection pools, and headers. Initializing a new Session inside each thread's run method ensures each thread has its own isolated session, avoiding race conditions and data corruption. This is the recommended practice for multithreaded scraping with requests.

Exam trap

PCPP1 often tests whether candidates assume requests.Session is thread-safe and can be shared globally, when in fact it must be instantiated per thread to avoid state corruption.

How to eliminate wrong answers

Option B is wrong because wrapping a shared Session in a threading.Lock would serialize all HTTP requests, eliminating the concurrency benefit and still risking subtle state issues; it is not the recommended pattern. Option C is wrong because sharing a single global Session across threads is unsafe due to concurrent mutation of cookies, headers, and connection pool state, leading to unpredictable behavior. Option D is wrong because disabling connection pooling with pool_connections=0 does not address thread safety and would degrade performance by forcing new connections per request.

20
MCQeasy

You are writing a Python script that needs to parse a URL and extract the query parameters. The URL is 'https://api.example.com/v1/items?limit=10&offset=20'. Which module should you use to reliably parse this URL and retrieve the value of 'limit'?

A.urllib.parse
B.urllib.request
C.requests
D.urlparse
AnswerA

The urllib.parse module provides functions like urlparse and parse_qs to break a URL into components and parse the query string into a dictionary. Using urlparse on the URL and then parse_qs on the query component will yield {'limit': ['10'], 'offset': ['20']}. This is the standard and reliable way to parse URLs in Python, handling encoding and edge cases correctly.

Why this answer

The urllib.parse module is specifically designed for parsing URLs. It provides urlparse to split a URL into scheme, netloc, path, query, etc., and parse_qs to parse the query string into a dictionary. This is the correct and standard way to extract query parameters like 'limit' from a URL in Python.

Exam trap

The trap here is confusing urllib.parse with urllib.request, or thinking that urlparse is a standalone module, when it is actually a function within urllib.parse.

21
MCQeasy

Which status code indicates that a requested resource has been successfully created?

A.201 Created
B.400 Bad Request
C.200 OK
D.204 No Content
AnswerA

HTTP 201 Created confirms the request succeeded and a new resource now exists at the location given in the response's Location header. This satisfies the stem's requirement for the status code signalling successful resource creation.

Why this answer

HTTP status code 201 Created indicates that the request has succeeded and has led to the creation of a new resource. It is typically returned in response to a POST or PUT request that creates a resource, and the response often includes a Location header pointing to the new resource. This is the standard, RFC 7231-defined code for successful resource creation.

Exam trap

PCPP1 often tests the confusion between 200 OK and 201 Created, since both indicate success; candidates must remember that 201 specifically signals resource creation, not just a successful response.

How to eliminate wrong answers

Option B is wrong because 400 Bad Request indicates the server cannot process the request due to client error (e.g., malformed syntax), not successful creation. Option C is wrong because 200 OK is a generic success code indicating the request succeeded but does not specifically signal resource creation. Option D is wrong because 204 No Content indicates success with no body to return, typically used for DELETE or PUT updates, not for creating a resource that should be referenced.

22
MCQmedium

You need to perform a HEAD request to check if a file exists on a server without downloading the body. How is this done with 'requests'?

A.requests.head(url)
B.requests.post(url, data={'type': 'head'})
C.requests.options(url)
D.requests.get(url, headers={'Method': 'HEAD'})
AnswerA

requests.head() issues an HTTP HEAD request, so the server returns only headers with no message body, satisfying the requirement to check file existence without downloading content. It mirrors requests.get() but uses the HEAD verb, which is the correct method for metadata-only checks.

Why this answer

The requests.head() method sends a HEAD request, which only retrieves headers.

23
MCQeasy

What is the primary difference between the 'socket.AF_INET' and 'socket.AF_INET6' address families?

A.AF_INET6 supports UDP only
B.AF_INET requires a password
C.AF_INET is faster than AF_INET6
D.AF_INET is for IPv4; AF_INET6 is for IPv6
AnswerD

AF_INET selects the IPv4 protocol stack, expecting addresses as (host, port) tuples with 32-bit hosts; AF_INET6 selects IPv6, using 128-bit addresses and four-element tuples. The stem asks for the primary difference, which is precisely the IP version each family binds sockets to.

Why this answer

AF_INET is for IPv4, while AF_INET6 is for IPv6 addressing.

24
MCQhard

In a multithreaded network application, you observe 'ConnectionResetError'. What is the most likely cause when using Python sockets?

A.The port is already in use by another process
B.The socket was never bound
C.The remote server closed the connection abruptly
D.The local thread pool is exhausted
AnswerC

ConnectionResetError is raised when the peer sends a TCP RST rather than a graceful FIN, which happens when the remote process terminates or drops the socket abruptly. This matches the stem's multithreaded socket scenario, where the server side closed without completing the normal shutdown handshake.

Why this answer

This occurs when the remote host closes the connection while the local end is still trying to send or receive data.

25
MCQmedium

You are using the socket module to create a TCP client. After creating the socket object, which method call is required to establish a connection to a remote server listening on 192.168.1.50 at port 8080?

A.sock.bind(('192.168.1.50', 8080))
B.sock.accept()
C.sock.connect(('192.168.1.50', 8080))
D.sock.listen(1)
AnswerC

connect() takes a single tuple of (host, port) and performs the TCP three-way handshake, binding the client socket to the remote endpoint at 192.168.1.50:8080. Alternatives such as bind() or accept() serve server-side roles, so connect() is the only call that establishes the outbound connection required here.

Why this answer

For a TCP client socket, after creating the socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM), the connect() method is what initiates the TCP three-way handshake with the remote server. Passing a tuple of (host, port) — here ('192.168.1.50', 8080) — tells the OS to open a connection to that endpoint. This is the client-side counterpart to the server's bind/listen/accept sequence.

Exam trap

PCPP1 often tests confusion between client-side and server-side socket methods — candidates must remember that connect() is for clients and bind()/listen()/accept() are for servers, and that bind() does not establish a connection.

How to eliminate wrong answers

Option A is wrong because bind() is used on the server side (or to bind a client to a specific local address) to associate the socket with a local address and port; calling bind() with a remote IP does not establish a connection. Option B is wrong because accept() is a server-side call that blocks waiting for an incoming connection and returns a new socket plus the client address — it is meaningless on a client socket. Option D is wrong because listen() is also server-side; it puts a bound socket into a listening state so it can accept incoming connections, and it does nothing for an outbound client connection.

26
MCQmedium

You are writing a Python tool that must connect to a REST API over HTTPS. The API's server certificate is signed by an internal corporate CA whose root certificate is stored in a file named corp-ca.pem. You use the requests library and need the connection to be verified against that specific CA while still performing normal hostname checking. Which call accomplishes this?

A.requests.get(url, verify=False)
B.requests.get(url, proxies={'https': 'corp-ca.pem'})
C.requests.get(url, cert='corp-ca.pem')
D.requests.get(url, verify='corp-ca.pem')
AnswerD

Passing the path of a CA bundle to verify makes requests use exactly that file as the trust store, so the internal root is trusted while standard certificate and hostname validation still run. It is the documented way to point the library at a private CA without disabling security.

Why this answer

The verify parameter accepts either a boolean or a path to a CA bundle. Supplying the path to the corporate root certificate causes requests to trust that CA in addition to performing the usual certificate chain and hostname validation. Disabling verification, configuring a client certificate, or setting a proxy does not achieve trusted validation against a private CA.

Exam trap

The trap here is assuming that pointing cert or proxies at a CA file changes which certificate authority is trusted, when only verify accepts a CA bundle path.

27
Multi-Selecthard

Which TWO of the following are true regarding the HTTP 'User-Agent' header?

Select 2 answers
A.It is used to encrypt the payload
B.It can be spoofed to mimic browsers
C.It identifies the client application to the server
D.It is automatically set by the socket module
E.It is mandatory for all HTTP requests
AnswersB, C

The User-Agent header is client-supplied text, so any value can be sent regardless of the actual software. Tools and scripts routinely set it to a browser string, satisfying the requirement that it can be spoofed to mimic browsers.

Why this answer

Option B is correct because the User-Agent header is a plaintext, client-supplied string with no cryptographic protection or server-side verification, so tools like curl, browsers, or scripts can freely set it to any value (e.g., 'Mozilla/5.0') to impersonate another client. Option C is correct because the User-Agent header's defined purpose in HTTP is to identify the requesting user agent — the client application, its version, and often the OS — to the server, which may use it for content negotiation, analytics, or bot detection. Option A is wrong because encryption is provided by TLS/HTTPS, not by any HTTP header; User-Agent carries no cryptographic function.

Option D is wrong because the socket module operates at the transport layer and has no knowledge of HTTP semantics; libraries like requests or http.client set User-Agent, not raw sockets. Option E is wrong because HTTP/1.1 only mandates the Host header for requests, and User-Agent is optional — many clients omit it or send an empty value.

28
Multi-Selectmedium

Which THREE of the following are correct regarding socket buffer sizes?

Select 3 answers
A.Buffer sizes are limited by the operating system
B.SO_RCVBUF sets the receiving buffer size
C.The buffer size has no effect on throughput
D.Setting a massive buffer always improves speed
E.Buffer size can be configured using setsockopt
AnswersA, B, E

Socket buffer sizes are bounded by kernel-level limits such as SO_RCVBUF and SO_SNDBUF maxima, so the operating system constrains how large buffers can be set. This is the actual constraint governing socket buffer configuration, not the Python socket module itself.

Why this answer

Option A is correct because socket buffer sizes are bounded by OS-level limits such as net.core.rmem_max and net.core.wmem_max on Linux, so an application cannot arbitrarily set them beyond what the kernel permits. Option B is correct because the SO_RCVBUF socket option specifically controls the size of the receive buffer used to hold incoming data before the application reads it. Option E is correct because setsockopt() is the standard API call used to configure socket options like SO_RCVBUF and SO_SNDBUF on a socket.

Option C is wrong because buffer size directly influences throughput, especially on high-bandwidth or high-latency links where too small a buffer limits the window. Option D is wrong because excessively large buffers can waste memory, increase latency, and do not guarantee faster transfer since throughput is also constrained by bandwidth, RTT, and application processing.

29
MCQmedium

You are building a Python script that consumes a REST API which returns paginated JSON responses. The API includes a 'next' link in the response body for the next page. You need to follow these links until all pages are retrieved. Which approach is most appropriate using the requests library?

A.Set the 'stream' parameter to True in the GET request to retrieve all pages in a single streaming response.
B.Use the requests.get() method with the 'params' argument to specify a page number, incrementing it until an empty response is received.
C.Use a while loop that sends a GET request to the current URL, parses the JSON, extracts the 'next' link, and updates the URL until 'next' is null.
D.Use the requests.Session object and call session.get() with the initial URL, relying on the session to automatically follow the 'next' links in the JSON body.
AnswerC

This approach correctly handles pagination by iteratively requesting each page, extracting the next link from the JSON response, and continuing until there are no more pages. It uses the requests library to send GET requests and parse JSON, which is straightforward and effective for APIs that provide next links in the body.

Why this answer

When an API returns a 'next' link in the JSON body, the correct way to paginate is to iteratively follow that link. This requires parsing the JSON, extracting the URL, and making subsequent requests until the link is absent or null. The requests library facilitates this with its get() method and .json() parsing.

Other options either misunderstand the features or assume a different pagination style.

Exam trap

The trap here is assuming that requests.Session automatically follows pagination links in the response body, or that streaming can combine pages, when in fact pagination logic must be implemented manually.

30
MCQeasy

You are developing a Python application that needs to retrieve data from a public REST API. The API returns JSON data and requires you to send a GET request with a custom User-Agent header. Which of the following code snippets correctly sends the request using the requests library?

A.requests.get(url, user_agent='MyApp/1.0')
B.requests.get(url, headers=('User-Agent', 'MyApp/1.0'))
C.requests.get(url, custom_headers={'User-Agent': 'MyApp/1.0'})
D.requests.get(url, headers={'User-Agent': 'MyApp/1.0'})
AnswerD

This snippet correctly uses the headers parameter, which accepts a dictionary of HTTP headers to send with the request. The User-Agent header is set to 'MyApp/1.0', fulfilling the requirement. This is the standard and recommended way to add custom headers in requests.

Why this answer

The requests library provides the headers parameter to specify custom HTTP headers. It accepts a dictionary where keys are header names and values are header values. This is the standard way to set a User-Agent or any other header.

The other options use non-existent parameters or incorrect data types, which would cause errors.

Exam trap

The trap here is confusing the parameter name or format, such as using user_agent instead of headers, or providing a tuple instead of a dictionary.

31
MCQhard

You are implementing a Python client that communicates with a REST API over HTTPS. The API uses a self-signed certificate. You need to verify the server's certificate against a custom CA bundle while also ensuring that the hostname is verified. Which approach correctly configures the 'requests' library?

A.Set the 'verify' parameter to False and manually check the certificate fingerprint.
B.Set the 'verify' parameter to the path of the custom CA bundle; hostname verification is automatically enabled.
C.Set the 'cert' parameter to the path of the custom CA bundle and set 'verify' to True.
D.Pass the path to the custom CA bundle to the 'verify' parameter and set 'verify_hostname' to True.
AnswerB

When you pass a path to a CA bundle to the 'verify' parameter, requests uses that bundle to verify the server's certificate. Hostname verification is performed by default as part of the SSL verification process. There is no need for an additional parameter. This approach correctly configures requests to use the custom CA and ensures hostname verification is active, meeting the scenario's requirements.

Why this answer

To use a custom CA bundle with requests, you pass the path to the bundle to the 'verify' parameter. This enables certificate verification against that bundle, and hostname verification is performed automatically as part of the SSL handshake. No additional parameter is needed for hostname verification, and disabling verification is insecure.

Exam trap

The trap here is thinking that there is a separate parameter for hostname verification, or confusing the 'cert' parameter (for client certificates) with the 'verify' parameter (for CA bundles).

32
Multi-Selecteasy

Which THREE of the following are valid HTTP request methods commonly used in RESTful API design?

Select 3 answers
A.SEND
B.DELETE
C.GET
D.POST
E.FETCH
AnswersB, C, D

DELETE is a standard HTTP request method used in RESTful design to remove the resource identified by the request URI. It satisfies the stem by being one of the valid methods commonly applied to REST endpoints.

Why this answer

GET (C), POST (D), and DELETE (B) are all standard HTTP request methods defined in RFC 7231 and are core to RESTful API design: GET retrieves a representation of a resource, POST creates a new resource or submits data to be processed, and DELETE removes the specified resource. These methods map directly to REST's CRUD semantics (Read, Create, Delete) and are idempotent or non-idempotent as appropriate (GET and DELETE are idempotent, POST is not). SEND (A) and FETCH (E) are not valid HTTP request methods; FETCH is a JavaScript browser API for making network requests, and SEND is not part of the HTTP method registry, so neither belongs in a RESTful API design discussion.

33
Multi-Selecteasy

Which TWO of the following are commonly used for debugging REST API integrations?

Select 2 answers
A.Hardcoding all credentials
B.Deleting the socket library
C.Increasing the CPU clock speed
D.Using a proxy tool to inspect traffic
E.Logging the request and response headers
AnswersD, E

A proxy tool intercepts HTTP traffic between client and server, exposing the actual request URLs, methods, payloads and status codes. This directly satisfies the need to debug REST API integrations, since it reveals what is genuinely transmitted rather than what the code intends to send.

Why this answer

Option D is correct because a proxy tool (e.g., Charles Proxy, Fiddler, or mitmproxy) acts as an intercepting man-in-the-middle that captures and displays the actual HTTP/HTTPS requests and responses, letting you inspect methods, URLs, status codes, and payloads for REST debugging. Option E is correct because logging request and response headers (e.g., Content-Type, Authorization, Accept, and custom headers) reveals exactly what the client sent and what the server returned, which is essential for diagnosing issues like missing auth tokens, wrong content negotiation, or unexpected status codes. The remaining options do not belong: hardcoding all credentials (A) is a security anti-pattern that exposes secrets and does nothing to aid debugging, deleting the socket library (B) would break networking entirely, and increasing the CPU clock speed (C) is a hardware performance tweak unrelated to inspecting or troubleshooting API traffic.

34
Multi-Selecthard

You are developing a Python application that uses the `requests` library to consume a REST API. You need to implement a retry mechanism for transient HTTP errors (e.g., 500, 502, 503, 504) and connection timeouts. Which TWO of the following approaches are valid and recommended for achieving this with `requests`? (Choose two.)

Select 2 answers
A.Set the `max_retries` parameter directly in the `requests.get()` call, e.g., `requests.get(url, max_retries=3)`.
B.Pass a `retry` parameter to `requests.get()` with a dictionary of retry settings, e.g., `requests.get(url, retry={'total': 3})`.
C.Use the `requests.Session` object and set `session.retries = 3`.
D.Use the `Retry` class from `urllib3.util.retry` and mount it to an `HTTPAdapter` on a `requests.Session` object.
E.Wrap the request in a `try/except` block and manually loop with a counter, catching `requests.exceptions.ConnectionError` and checking `response.status_code` for server errors.
AnswersD, E

The `requests` library uses `urllib3` under the hood, and `urllib3.util.retry.Retry` allows fine-grained control over retries, including which status codes to retry on, backoff factors, and total retries. By creating an `HTTPAdapter` with a `Retry` instance and mounting it to a `Session`, you can automatically retry failed requests. This is the recommended, robust way to implement retries.

Why this answer

The recommended way to add retries in `requests` is by using `urllib3`'s `Retry` class with an `HTTPAdapter` mounted on a `Session`. Alternatively, you can manually implement retry logic with loops and exception handling. The other options reference non-existent parameters or attributes.

Both correct approaches provide control over transient errors and timeouts.

Exam trap

The trap here is assuming that `requests` has built-in retry parameters like `max_retries` or `retry` in its top-level API, when retries must be configured via adapters or manual loops.

35
MCQhard

You are building a client for a REST API that requires an OAuth 2.0 bearer token. The token is long-lived and stored in an environment variable. You want every request in a session to carry the Authorization header without repeating the header setup at each call site. Which approach is correct and idiomatic with the requests library?

A.Create a requests.Session, set session.headers.update({'Authorization': f'Bearer {token}'}), and issue calls through that session.
B.Pass auth=('Bearer', token) to each request so the library builds the header.
C.Set os.environ['HTTP_AUTHORIZATION'] = f'Bearer {token}' before each call.
D.Subclass requests.Session and override send to inject the header after the request is prepared.
AnswerA

A Session object holds default headers that are merged into every request made through it, so updating session.headers once applies the bearer token to all calls. This is idiomatic, avoids repetition, and also reuses the underlying TCP connection for better performance.

Why this answer

A Session stores default headers that are merged into each prepared request, so updating session.headers with the Authorization bearer value applies authentication everywhere the session is used. Environment variables are not consulted by requests for outgoing headers, tuple-based auth produces Basic credentials, and overriding send is needlessly complex compared with the supported header mechanism.

Exam trap

The trap here is believing the auth tuple can express any scheme, when in fact it only produces HTTP Basic credentials from a username and password.

36
MCQmedium

You wrote a small REST client that calls `requests.get('https://api.example.com/v1/items', timeout=5)`. Under normal network load the call succeeds, but the server occasionally takes longer than 5 seconds to start sending the response body while the TCP connection is already established. You want to allow up to 5 seconds for the connection to be established and up to 30 seconds for the server to send data after the connection is made. Which call achieves this?

A.requests.get('https://api.example.com/v1/items', timeout=30)
B.requests.get('https://api.example.com/v1/items', timeout=(30, 5))
C.requests.get('https://api.example.com/v1/items', timeout=(5, 30))
D.requests.get('https://api.example.com/v1/items', timeout=5, read_timeout=30)
AnswerC

The timeout parameter accepts a tuple where the first value is the connect timeout (maximum time to establish the TCP connection) and the second is the read timeout (maximum time to wait for a chunk of data after the connection is established). Passing (5, 30) exactly matches the requirement: 5 seconds to connect, 30 seconds to receive data.

Why this answer

The requests library accepts a timeout tuple of (connect_timeout, read_timeout). Only the tuple form allows different limits for establishing the connection and for waiting on data. The scenario explicitly asks for 5 seconds to connect and 30 seconds to read, so the correct call uses (5, 30).

Any single value or reversed tuple misconfigures one of the two phases.

Exam trap

The trap here is assuming a single timeout value or a named keyword controls both connect and read phases independently.

37
MCQhard

You are implementing a Python client that uses the `socket` module to communicate with a server. The server sends data in chunks, and you need to ensure you receive all data until the connection is closed by the server. Which approach correctly reads all data from the socket?

A.data = b''; while True: chunk = sock.recv(4096); if not chunk: break; data += chunk
B.data = sock.recv_all()
C.data = sock.recv(1024)
D.data = sock.recv(0)
AnswerA

This loop repeatedly calls `recv(4096)` and appends chunks to a bytes object until `recv` returns an empty bytes object (`b''`), which signals that the server has closed the connection. This is the correct pattern to read all data from a TCP socket until EOF. It handles arbitrary data sizes and ensures no data is missed.

Why this answer

To read all data from a TCP socket until the server closes the connection, you must call `recv()` in a loop, accumulating chunks until `recv()` returns an empty bytes object. A single `recv()` call may not return all data. The `socket` module does not provide a `recv_all()` method, and `recv(0)` reads nothing.

Thus, the loop approach is correct.

Exam trap

The trap here is assuming a single `recv()` call retrieves all data, or that a convenience method like `recv_all()` exists.

38
Multi-Selectmedium

You are writing a REST client that must handle HTTP error responses robustly. For each response, you want to detect server errors and extract the error message returned in a JSON body. Which TWO of the following approaches are correct and safe? (Choose two.)

Select 2 answers
A.Call response.json() unconditionally on every response without checking the Content-Type header.
B.Use response.status_code >= 400 to decide whether to parse the error body, then call response.json() to extract the error message.
C.Assume any response with status_code 200 contains valid data and skip further validation.
D.Call response.raise_for_status() inside a try block and catch requests.exceptions.HTTPError to handle 4xx and 5xx responses.
E.Ignore the status code and rely solely on the presence of an 'error' key in the JSON body.
AnswersB, D

Checking status_code directly is explicit and avoids relying on exceptions. Calling response.json() on an error response is valid when the API documents JSON error bodies. This approach gives full control over parsing and is safe as long as the body is known to be JSON.

Why this answer

Both raise_for_status() with HTTPError handling and explicit status_code checks are valid, safe patterns for detecting HTTP errors. The first centralizes error handling via exceptions, while the second gives explicit control and is useful when the API returns structured JSON error bodies. The other options either skip essential validation or assume JSON without verifying it.

Exam trap

The trap here is assuming a 200 status guarantees a valid payload or that every response body can be parsed as JSON.

39
MCQhard

You are designing a Python microservice that exposes a REST API. A client sends a PUT request to update a resource with a JSON body. Your service must ensure idempotency: if the same request is received multiple times, the resource should end up in the same state. Which HTTP method and semantics should you implement to guarantee idempotency for updates?

A.Use POST because it can carry a body and is commonly used for updates, and implement a custom idempotency key header to detect duplicates.
B.Use PATCH because it allows partial updates, and implement versioning to prevent duplicate changes.
C.Use PUT because it replaces the entire resource with the request payload, and repeating the same PUT results in the same final state.
D.Use GET with a query parameter that contains the new state, because GET is safe and idempotent.
AnswerC

PUT is defined as idempotent: sending the same request multiple times has the same effect as sending it once, because it replaces the resource with the provided representation. This matches the requirement to guarantee idempotency for updates without additional application-level duplicate detection. The server should treat the payload as the complete new state of the resource.

Why this answer

PUT is the HTTP method specifically designed for idempotent updates: it replaces the target resource with the request payload, so repeating the same request yields the same state. POST and PATCH do not inherently guarantee idempotency, and GET must not be used for updates. Implementing PUT correctly ensures that duplicate requests do not cause unintended side effects.

Exam trap

The trap here is confusing idempotency with safety or assuming that any method with a body can be made idempotent with headers.

40
MCQhard

When implementing a timeout in 'requests.get()', what is the consequence of setting it as a single float (e.g., timeout=5)?

A.It only limits the read phase
B.It causes an error because a tuple is expected
C.It only limits the connection phase
D.It limits both the connection and read time to 5 seconds
AnswerD

Passing a single float sets both the connect and read timeouts to that value, so requests.get() aborts if the TCP connection is not established within 5 seconds or if no bytes arrive during any 5-second read window.

Why this answer

Providing a single value sets both the connect and read timeouts to that value.

41
MCQmedium

When working with raw sockets, what does the 'socket.SOCK_STREAM' constant represent?

A.UDP datagram sockets
B.Raw network sockets
C.TCP connection-oriented sockets
D.Unix domain sockets only
AnswerC

SOCK_STREAM selects a connection-oriented, reliable byte-stream transport, which on IP networks maps to TCP. It satisfies the stem's requirement by guaranteeing ordered, error-checked delivery, unlike SOCK_DGRAM, which provides connectionless UDP datagrams with no delivery guarantee.

Why this answer

socket.SOCK_STREAM designates a reliable, connection-oriented byte stream, which in practice maps to TCP (or a Unix-domain stream socket). The Python socket module passes this constant to socket() to select the transport semantics, so SOCK_STREAM sockets guarantee ordered, error-checked delivery via the TCP three-way handshake. This is why HTTP, SMTP, and SSH clients built on Python sockets use SOCK_STREAM.

Exam trap

PCPP1 often tests the confusion between socket type constants (SOCK_STREAM vs SOCK_DGRAM vs SOCK_RAW) and address family constants (AF_INET vs AF_UNIX), tricking candidates into thinking SOCK_STREAM implies a specific family or protocol.

How to eliminate wrong answers

Option A is wrong because UDP datagram sockets are represented by socket.SOCK_DGRAM, which is connectionless and message-oriented with no delivery guarantees. Option B is wrong because raw sockets are selected with socket.SOCK_RAW, which bypasses the transport layer and requires elevated privileges to craft packets directly. Option D is wrong because Unix domain sockets are chosen via the address family (AF_UNIX), not the socket type; SOCK_STREAM can be used with AF_UNIX, AF_INET, or AF_INET6, so it is not limited to Unix domain sockets.

42
MCQeasy

Which standard Python library module is used for lower-level networking and creating server/client sockets?

A.http.server
B.requests
C.networking
D.socket
AnswerD

The socket module exposes the BSD socket interface directly, providing socket(), bind(), listen() and accept() for building servers and clients. It is the standard library's low-level networking foundation, satisfying the stem's requirement for lower-level socket creation rather than higher-level protocols.

Why this answer

The socket module is Python's standard library interface to the BSD sockets API, providing low-level networking primitives for creating TCP/UDP clients and servers. It exposes functions like socket(), bind(), listen(), accept(), connect(), send(), and recv(), making it the correct answer for lower-level networking. Higher-level modules like http.server and third-party libraries like requests are built on top of it.

Exam trap

PCPP1 often tests the distinction between standard library and third-party modules — candidates must recognize that requests is not part of the standard library and that 'networking' is not a real module, leaving socket as the only valid low-level option.

How to eliminate wrong answers

Option A is wrong because http.server is a high-level module for building simple HTTP servers; it abstracts away socket-level details and is not used for general lower-level networking. Option B is wrong because requests is a third-party HTTP client library (not part of the standard library) that operates at the HTTP protocol level, not the socket level. Option C is wrong because there is no standard library module named 'networking' in Python — this is a fabricated distractor.

43
MCQeasy

You are writing a script that downloads a large file from a REST endpoint using `requests.get(url, stream=True)`. You want to write the content to disk in chunks rather than loading it all into memory. Which approach correctly implements chunked reading?

A.file.write(response.raw.read())
B.for chunk in response.iter_content(chunk_size=8192): file.write(chunk)
C.for chunk in response.iter_lines(): file.write(chunk)
D.file.write(response.content)
AnswerB

iter_content() yields the response body in chunks of the specified size, allowing you to write each chunk to disk without holding the entire file in memory. This is the documented pattern for streaming downloads with requests and works with stream=True to avoid buffering the full response.

Why this answer

Streaming a large download requires reading the body incrementally. The iter_content() method yields chunks of a specified size and is the standard way to write streaming responses to disk without buffering the whole payload. Using response.content or response.raw.read() without a size loads everything into memory, while iter_lines() is intended for line-delimited text streams.

Exam trap

The trap here is confusing iter_lines(), which splits on newlines, with iter_content(), which yields fixed-size byte chunks suitable for binary files.

44
Multi-Selectmedium

Which TWO of the following are potential pitfalls when using multithreading for network operations in Python?

Select 2 answers
A.Race conditions when accessing shared state
B.The GIL prevents true parallelism for CPU-bound tasks
C.Threads always execute slower than single-threaded code
D.Threads consume more memory than processes
E.Socket objects are automatically thread-safe
AnswersA, B

Shared mutable state accessed by multiple threads without locking permits interleaved reads and writes, producing race conditions and corrupted results. This satisfies the stem's pitfall criterion because Python's GIL serialises bytecode execution but does not make compound operations atomic, so concurrent network handlers updating shared buffers remain unsafe.

Why this answer

Option A is correct because when multiple threads access and modify shared state (such as a shared socket buffer, connection pool, or counter) without proper synchronization primitives like locks, race conditions can occur, leading to corrupted data or unpredictable behavior. Option B is correct because Python's Global Interpreter Lock (GIL) allows only one thread to execute Python bytecode at a time, so multithreading does not achieve true parallelism for CPU-bound tasks—though it can still help with I/O-bound network operations where threads block on socket calls. Option C is incorrect because threads do not always execute slower than single-threaded code; for I/O-bound network operations, multithreading often improves throughput by overlapping waiting periods.

Option D is incorrect because threads within a process share the same memory space and typically consume less memory overhead than separate processes, not more. Option E is incorrect because socket objects in Python are not automatically thread-safe; concurrent access to the same socket from multiple threads can cause data corruption or errors unless explicitly synchronized.

45
Multi-Selecthard

You are designing a Python REST API client that must handle HTTP errors gracefully. The client uses the requests library. Which TWO of the following statements about error handling with requests are correct? (Choose two.)

Select 2 answers
A.The response.raise_for_status() method raises an HTTPError if the HTTP status code indicates a client error (4xx) or server error (5xx).
B.The requests.exceptions.ConnectionError is raised when the server returns a 500 Internal Server Error status code.
C.The requests.exceptions.Timeout exception is raised when the server returns a 408 Request Timeout status code.
D.The response.status_code attribute returns the HTTP status code as an integer, and you can compare it directly to constants like requests.codes.ok.
E.By default, requests automatically raises an exception for any HTTP status code other than 200 OK.
AnswersA, D

This statement is correct. The raise_for_status() method checks the status code and raises an HTTPError exception for 4xx and 5xx responses. It is a convenient way to ensure that only successful responses (2xx) proceed, and it provides access to the response object for further inspection.

Why this answer

The raise_for_status() method is the idiomatic way to trigger exceptions for HTTP error statuses, and status_code provides the numeric code for manual checks. The other statements confuse network-level exceptions with HTTP status codes, or incorrectly assume automatic error raising. Understanding these distinctions is crucial for robust API clients.

Exam trap

The trap here is conflating network exceptions (like ConnectionError or Timeout) with HTTP status code errors, and assuming requests automatically raises exceptions for all non-200 responses.

46
Multi-Selecteasy

Which THREE of the following are standard ways to handle API authentication?

Select 3 answers
A.OAuth 2.0
B.API Keys
C.Public IP Whitelisting
D.Basic Authentication
E.Hardcoding passwords in code
AnswersA, B, D

OAuth 2.0 is a delegated authorisation framework where clients obtain access tokens from an authorisation server, avoiding credential sharing. It satisfies the scenario's requirement for a standard API authentication method, unlike ad-hoc schemes, and is widely adopted for third-party access.

Why this answer

OAuth 2.0 (A) is a standard authorization framework that issues access tokens via grant flows (authorization code, client credentials, etc.), allowing scoped, revocable API access without sharing credentials. API Keys (B) are a widely used standard mechanism where a unique key identifies and authenticates the calling application, typically passed in a header or query parameter. Basic Authentication (D) is an HTTP-standard scheme (RFC 7617) that sends a Base64-encoded username:password in the Authorization header, commonly used for simple API authentication over TLS.

Public IP Whitelisting (C) is a network access control, not an authentication method, since it does not verify caller identity. Hardcoding passwords in code (E) is an insecure anti-pattern that exposes credentials and is not a standard authentication approach.

47
MCQhard

You are investigating a network bottleneck in your Python application using `requests`. If you aren't using a `Session` object, what performance-related behavior should you expect?

A.Each request will perform a full TCP handshake
B.The application will use more memory
C.Connection pooling will be enabled by default
D.The server will block your IP immediately
AnswerA

Without a Session, each requests call opens a fresh connection, repeating the full TCP handshake and TLS negotiation per request. This satisfies the bottleneck scenario: connection setup overhead accumulates across calls, whereas a Session pools and reuses connections via keep-alive.

Why this answer

Without a Session, each request creates a new TCP connection, incurring the cost of a three-way handshake every time.

48
MCQeasy

You are writing a Python script that needs to send a GET request to a REST API and parse the JSON response. The API requires an API key passed as a query parameter. Which code snippet correctly performs this request using the requests library?

A.requests.get('https://api.example.com/data', data={'api_key': '12345'})
B.requests.get('https://api.example.com/data?api_key=12345')
C.requests.get('https://api.example.com/data', params={'api_key': '12345'})
D.requests.get('https://api.example.com/data', headers={'api_key': '12345'})
AnswerC

This uses the params argument to pass a dictionary of query parameters, which requests will URL-encode and append to the URL. It correctly sends the API key as a query parameter, as required by the scenario. The response can then be parsed with response.json(). This is the standard and correct way to include query parameters in a GET request.

Why this answer

The params argument in requests.get() is the correct way to pass query parameters. It automatically URL-encodes the dictionary and appends it to the URL. Using headers or data would not place the API key in the query string as required.

Manually constructing the URL is error-prone and less secure.

Exam trap

The trap here is confusing the data argument with params, or assuming that any argument that accepts a dictionary will work for query parameters.

49
MCQmedium

When using the 'socket' module, what is the effect of calling 'socket.settimeout(5.0)' on a socket object?

A.It sets the send buffer size to 5.0 bytes
B.It causes the operation to raise a socket.timeout after 5 seconds
C.It blocks the thread for exactly 5 seconds
D.It forces the socket to close after 5 seconds of inactivity
AnswerB

Setting a socket timeout places the descriptor in non-blocking mode with a deadline: blocking calls such as `recv()`, `send()` or `accept()` raise `socket.timeout` once 5 seconds elapse without completing. This satisfies the stem's requirement that the operation itself fails after the specified interval rather than waiting indefinitely.

Why this answer

The settimeout() method sets a timeout in seconds for subsequent socket operations. If the operation does not complete within the time, a socket.timeout exception is raised.

50
MCQhard

In Python socket programming, what does the 'SO_REUSEADDR' socket option achieve?

A.It speeds up data transmission
B.It allows the address to be reused immediately after the server stops
C.It enables broadcasting on the socket
D.It prevents the socket from closing
AnswerB

SO_REUSEADDR lets the socket bind to a local address still in TIME_WAIT after the server stops, avoiding 'Address already in use' errors. It satisfies the constraint of restarting the server immediately without waiting for the OS to release the port.

Why this answer

It allows the socket to bind to a port that is in a TIME_WAIT state, commonly used to restart servers quickly.

51
MCQhard

You are designing a REST client that must call an endpoint protected by OAuth 2.0 using the client credentials grant. The authorization server expects the client identifier and client secret to be sent in the request body as `application/x-www-form-urlencoded`, along with `grant_type=client_credentials`. Which `requests` call correctly obtains the token?

A.requests.post(token_url, data={'grant_type': 'client_credentials', 'client_id': cid, 'client_secret': secret})
B.requests.post(token_url, json={'grant_type': 'client_credentials', 'client_id': cid, 'client_secret': secret})
C.requests.post(token_url, auth=(cid, secret), data={'grant_type': 'client_credentials'})
D.requests.get(token_url, params={'grant_type': 'client_credentials', 'client_id': cid, 'client_secret': secret})
AnswerA

The data parameter encodes the dictionary as application/x-www-form-urlencoded, which is exactly what the OAuth 2.0 token endpoint expects for the client credentials grant. Including grant_type, client_id, and client_secret in the body matches the server requirement described in the scenario.

Why this answer

OAuth 2.0 token requests use POST with application/x-www-form-urlencoded bodies. The data parameter in requests performs that encoding automatically. Sending the grant type and client credentials in the body, rather than as Basic auth or JSON, satisfies the server's stated expectations and returns the access token needed for subsequent API calls.

Exam trap

The trap here is conflating HTTP Basic authentication with OAuth 2.0 client authentication and assuming JSON is universally accepted by token endpoints.

52
MCQhard

You are using 'concurrent.futures.ThreadPoolExecutor' to fetch data from multiple REST APIs. What happens if an exception is raised inside a thread?

A.The exception is ignored by the ThreadPoolExecutor
B.The entire program crashes immediately
C.The thread dies silently without notification
D.The exception is stored and raised when calling future.result()
AnswerD

ThreadPoolExecutor captures any exception raised inside a worker and stores it on the Future; it is not propagated in the worker thread. Calling future.result() re-raises that stored exception in the calling thread, satisfying the stem's scenario.

Why this answer

Exceptions raised in a future are captured and re-raised when calling result() on the Future object returned by submit().

53
Multi-Selecthard

Which TWO of the following statements about the Python 'requests' library are correct?

Select 2 answers
A.It uses 'urllib3' internally for connection pooling
B.It does not support HTTPS
C.It is part of the standard library
D.It is thread-safe by default for all operations
E.It automatically closes connections for every request if not using a Session
AnswersA, E

Leveraging 'urllib3' beneath its API, 'requests' reuses TCP connections through pooling, avoiding a fresh handshake per call. This satisfies the stem's requirement for a true statement about the library's internals, since connection reuse is genuinely delegated to that lower-level dependency.

Why this answer

Option A is correct because the requests library is built on top of urllib3, which provides the underlying connection pooling and HTTP transport capabilities. Option E is correct because when you call requests.get() or similar top-level functions without using a Session object, requests creates a temporary Session internally, performs the request, and then closes the connection rather than reusing it. Option B is incorrect because requests fully supports HTTPS and TLS/SSL verification.

Option C is incorrect because requests is a third-party package that must be installed via pip, not part of the Python standard library. Option D is incorrect because requests is not guaranteed thread-safe for all operations; while Session objects can be used across threads with care, the library does not provide blanket thread-safety guarantees.

54
MCQhard

You are building a REST client that needs to handle 429 Too Many Requests status codes. Which strategy is most effective when implementing an automatic retry mechanism?

A.Implement an exponential backoff strategy with jitter
B.Switch to a different base URL immediately
C.Ignore 429 errors and continue execution
D.Retry immediately in a loop until successful
AnswerA

Exponential backoff with jitter progressively lengthens delays between retries while randomising them, preventing thundering-herd synchronisation. This directly addresses the 429 constraint by spacing retries so the client stops overwhelming the rate-limited server, unlike fixed-interval retries that keep colliding.

Why this answer

Implementing exponential backoff ensures that you do not overwhelm the server while waiting for the rate limit to reset.

55
MCQeasy

When using the 'requests' library to perform a GET request, which parameter should be passed to the 'params' argument to include query string parameters in the URL?

A.A tuple of values
B.A single formatted string
C.A list of strings
D.A dictionary
AnswerD

The params argument accepts a dictionary of key-value pairs, which requests URL-encodes and appends to the query string. Passing a dictionary therefore satisfies the stem's requirement to include query string parameters in the GET request URL.

Why this answer

The requests library's params argument accepts a dictionary (or list of tuples) that it URL-encodes and appends as a query string. Passing a dict like {'q': 'python', 'page': 2} produces ?q=python&page=2 automatically. This is the idiomatic and documented usage for GET query parameters.

Exam trap

PCPP1 often tests whether candidates know that params expects a mapping (dict) or sequence of two-tuples, not a pre-formatted string or bare list, since manual URL building is a common but incorrect habit.

How to eliminate wrong answers

Option A is wrong because a tuple of values alone lacks keys and would not map to query parameter names; requests expects key-value pairs, not bare values. Option B is wrong because a single formatted string would be treated as a raw value or require manual URL construction, defeating the purpose of params and risking encoding errors. Option C is wrong because a list of strings lacks key-value structure; while a list of tuples is valid, a plain list of strings is not the documented form and would not produce correct query parameters.

56
MCQhard

You are designing a Python application that consumes a REST API which returns JSON data. The API responses can be large, and you need to process the JSON incrementally to avoid loading the entire response into memory. The server supports chunked transfer encoding. Which of the following techniques should you use with the 'requests' library to stream the response and parse it incrementally?

A.Set stream=True in the request and use response.iter_content() to read chunks, then parse each chunk with a streaming JSON parser like ijson.
B.Use response.json() directly; it automatically streams and parses the JSON without loading everything into memory.
C.Use requests.get() with a large timeout and rely on the operating system's memory management to handle the response.
D.Set stream=True and then call response.json() to parse the streamed data.
AnswerA

Setting 'stream=True' prevents 'requests' from immediately downloading the entire response body. You can then use 'response.iter_content()' to iterate over the response data in chunks. To parse JSON incrementally, you need a streaming parser like 'ijson' that can process partial JSON data. This approach minimizes memory usage, which is critical for large responses.

Why this answer

To process large JSON responses incrementally with 'requests', you must enable streaming with 'stream=True' and then read the response in chunks using 'response.iter_content()'. Since JSON is not inherently line-delimited, you need a streaming parser like 'ijson' to parse the chunks as they arrive. This avoids loading the entire response into memory, making it suitable for large datasets.

Exam trap

The trap here is thinking that 'response.json()' works with streaming, or that setting 'stream=True' alone is enough without a streaming JSON parser.

57
Multi-Selecthard

You are implementing a REST API client in Python using the 'requests' library. The API requires authentication using OAuth 2.0. You need to obtain an access token and then use it to authenticate subsequent requests. Which TWO of the following statements about handling OAuth 2.0 with 'requests' are correct? (Choose two.)

Select 2 answers
A.OAuth 2.0 access tokens are typically sent as query parameters in the URL.
B.You can use the 'requests-oauthlib' library to handle the OAuth 2.0 flow, including token refresh.
C.The 'requests' library automatically refreshes expired OAuth 2.0 tokens when using the 'auth' parameter.
D.The 'requests' library includes built-in support for OAuth 2.0 token management.
E.You can manually add the access token to requests by setting the 'Authorization' header to 'Bearer <token>'.
AnswersB, E

'requests-oauthlib' is a popular extension that integrates OAuth 2.0 with 'requests'. It provides 'OAuth2Session', which manages token acquisition, storage, and automatic refreshing. This is the recommended approach for complex OAuth flows, as it handles redirects, state parameters, and token expiration, reducing the risk of manual errors.

Why this answer

Handling OAuth 2.0 with 'requests' typically involves either using a specialized library like 'requests-oauthlib' for full flow management, or manually adding the Bearer token to the Authorization header if you already have a valid token. The core 'requests' library does not provide built-in OAuth 2.0 support, and sending tokens as query parameters is insecure and not recommended.

Exam trap

The trap here is assuming that 'requests' has built-in OAuth 2.0 support or that the 'auth' parameter handles token refresh, when in fact it is for Basic Authentication.

58
MCQmedium

You are consuming a REST API that returns data in JSON format. After calling response.json(), you notice the data contains nested dictionaries. What is the most Pythonic way to handle a missing key in the response dictionary safely?

A.Wrap the access in a try-except KeyError block
B.Check 'if 'key' in response.json():' before access
C.Use response.json()['key'] and assume the API schema is always correct
D.Use response.json().get('key', default_value)
AnswerD

dict.get returns the supplied default when the key is absent, avoiding a KeyError without try/except. This handles missing keys in the nested JSON-derived dictionary safely and concisely, satisfying the stem's requirement for the most Pythonic approach.

Why this answer

The dict.get() method provides a way to access a key with a default value if the key does not exist, preventing a KeyError.

59
MCQmedium

How do you properly handle a non-200 status code when using 'requests' if you want to avoid manual status code checking?

A.Use response.raise_for_status()
B.Use a decorator on the request function
C.Check response.error
D.The library raises an exception by default
AnswerA

`response.raise_for_status()` inspects the status code internally and raises an `HTTPError` exception for any 4xx or 5xx response, so you never write an explicit `if response.status_code != 200` check. Wrapping the call in `try`/`except requests.exceptions.HTTPError` satisfies the stem's requirement to avoid manual status code checking.

Why this answer

Calling response.raise_for_status() will raise an HTTPError exception if the status code indicates an error (4xx or 5xx).

60
MCQmedium

You are writing a Python script that must download a large file from a REST API endpoint. The file is several gigabytes, and you want to avoid loading it entirely into memory. Which approach using the requests library is most memory-efficient?

A.Use requests.get(url).content to get the raw bytes and write them to a file in one operation.
B.Use requests.get(url, timeout=300) and then use shutil.copyfileobj(response.raw, file) to copy the raw stream to a file.
C.Use requests.get(url, stream=True) and call response.raw.read() to read the entire raw stream at once.
D.Use requests.get(url, stream=True) and iterate over response.iter_content(chunk_size=8192), writing each chunk to a file.
AnswerD

Setting stream=True defers downloading the response body until you access it. Then iter_content() yields chunks of the specified size, allowing you to write them to disk incrementally. This keeps memory usage low and constant, regardless of file size. It is the recommended approach for downloading large files with requests.

Why this answer

Using stream=True prevents the response body from being downloaded immediately. Iterating over iter_content() with a chunk size writes data to disk incrementally, keeping memory usage low. Other methods either load the entire response into memory or fail to stream properly.

This is the standard pattern for large file downloads with requests.

Exam trap

The trap here is assuming that stream=True alone is sufficient, without also using iter_content() to read in chunks; reading the raw stream all at once still consumes memory.

61
MCQhard

You are building a custom HTTP client and need to handle persistent connections (keep-alive). What is the primary role of the 'Connection' header?

A.To signal that the server is alive
B.To request the reuse of the TCP connection
C.To encrypt the connection
D.To set the timeout for the connection
AnswerB

The Connection header signals whether the TCP connection should stay open after the current exchange, with keep-alive requesting reuse rather than closure. This satisfies the persistent-connection requirement, letting subsequent requests travel over the same socket instead of triggering a new handshake.

Why this answer

The 'Connection: keep-alive' header tells the server that the client wants to reuse the same TCP connection for multiple requests.

62
Multi-Selecteasy

Which THREE of the following are valid ways to pass data to a REST API using 'requests'?

Select 3 answers
B.socket
C.url
D.params
E.data
AnswersA, D, E

The json parameter accepts a Python object, serialises it to JSON and sets the Content-Type header to application/json automatically. This satisfies the stem's requirement for passing data to a REST API, differing from data, which sends raw form-encoded bytes without JSON serialisation.

Why this answer

Option A, json, is correct because passing a Python object to the json= parameter serializes it to JSON and sends it in the request body with Content-Type: application/json, which is the standard way to submit JSON payloads to a REST API. Option D, params, is correct because params= appends a dictionary of key/value pairs as a URL query string (e.g., ?key=value), which REST APIs commonly use for filtering, pagination, or search arguments. Option E, data, is correct because data= sends a dictionary or bytes as the request body, typically form-encoded (application/x-www-form-urlencoded) for POST/PUT/PATCH requests to REST endpoints.

Option B, socket, is not a requests parameter at all — it refers to low-level network programming, not the requests library's API. Option C, url, is not a data-passing mechanism; the url argument specifies the endpoint address, not the payload or query data itself.

63
MCQmedium

Your team uses a REST API that requires a Bearer token in the Authorization header for every request. You want to configure a `requests.Session` so that all requests made through it automatically include this header, and you also want to reuse the underlying TCP connection across calls. Which approach is correct?

A.Set requests.default_headers['Authorization'] = 'Bearer ' + token and call requests.get(url).
B.Call requests.get(url, headers={'Authorization': 'Bearer ' + token}) for every request.
C.Create a Session, set session.headers.update({'Authorization': 'Bearer ' + token}), and use session.get() for subsequent calls.
D.Create a Session and pass auth=('Bearer', token) to session.get() on each call.
AnswerC

Session objects persist headers across requests and reuse the underlying connection pool, which enables keep-alive and reduces latency. Updating session.headers once applies the Authorization header to every request made through that session, exactly matching the requirement.

Why this answer

A requests.Session maintains a connection pool and a persistent set of headers. Setting the Authorization header once on the session applies it to all requests made through that session, and the underlying urllib3 connection pool reuses TCP connections for the same host. This satisfies both the authentication and connection reuse requirements.

Exam trap

The trap here is using the auth parameter for a Bearer token, which produces Basic authentication instead of the required Authorization header format.

Ready to test yourself?

Try a timed practice session using only Networking And Restful Apis questions.