Communication Protocols - HW3
Asavoae Cosmin-Stefan, 321CD
'Borrowed' library
For this assignment I chose to go with parson for parsing & working with
JSONpayloads.
Notable API calls
Because this implementation follows closely the given specs (and most of the calls only send a request and print the result), I chose to detail only the more complex API calls and the helpers I've made to create a better program flow.
context_t
This is not an API call, but is an important part of the calls that are made.
The
context_tstores the runtime information about
- Admin session cookie
- User session cookie
- User access JWT
The
cookiefield is used for storing the session cookie that will be used for the next API call. This avoids duplicate functions for both the user and admin requests.
login / logout
These are basic API calls, but they also update / delete the
user / admincookie stored inside thecontext(also the JWT for users)
add_collection
This API call makes use of the
create_collection&update_collectionhelpers to:
- Create a collection with the given title
- Add movies using the provided
movie_id[i]
The call reports an error if:
- The collection couldn't be created
- Any movie couldn't be added (or it doesn't exist)
purge
While not being a required command,
purgeis used during debugging to delete all the users created by the admin.
Flow:
- Get all the users
- Use the response to make a
delete_usercall for every user
Helpers
To simplify my work, I've created some helper functions for:
- Sending / Receiving TCP packets
- Sending HTTP requests
- Parsing HTTP responses
- Constructing API payloads
- Making API calls
- Dispatching commands
TCP Helpers
send_tcp&recv_tcpare used for communicating with the HTTP server. Not much to be said about them considering that they're reused fromHW2.
send_request
This function builds the HTTP payload to be sent to the server based on the parameters present in
req. A cookie is set if thecontextcookie pointer is valid, the same for the JWT. The provided JSONbodyis serialized and appended at the end (if it exists).
After the server responds, the packet is then parsed and returned.
parse_response
This helper reads the HTTP response from the server and builds the body into a JSON value. The functions returns a
response_twhich contains thestatuscode of the result, anycookiethat was set and the deserialized JSON body.
build_body
Using the provided
fieldsand theirtypes, this helper asks the user for input and builds a JSON value to be used as the body for an HTTP request.
build_path
Asks the user for the provided
fieldvalue and concatenates it to the providedpath. A new string is returned, but it is reused by the function on every call (it's static, duh).
send_api
This is a beefed-up version of
send_requestwhich takes care of:
- Setting the correct
cookie- Making the HTTP request
- Handling a basic
SUCCESSorERROR- Discarding the response if it will not be used or an error occurred
- Returning whether the call was successful or not
If the response doesn't contain a
messageorerrorfield, the fallbacks provided inreqwill be used.
If the
respointer is notNULL, the helper will store the response in it (also if the call was successful).
d_table_t
To avoid writing a tower if
if-else-ifstatements, I decided to use adispatch table.
Each entry contains the
command nameand its correspondingfunction pointer
On each command input, the table is searched for the provided name, making the corresponding API call or quitting if it's invalid
Personal Notes (Feedback)
Please note that these are just things I found annoying while solving this assignment and can be skipped
The
collectionqueries are the odd ones among the commands. If every other command demanded a JSON payload with exact fields, this 'family' of queries needs to pass mostly pairs of IDs using the API path, instead of one ID for the collection and a movie payload.While not hard to get around, it just broke the whole flow I had going with the other queries, making me give up on the whole
build_*idea and resort to just raw-dogging the params in the functions themselves.
Why on earth is the
ratingfield from theget_movieresponse astringinstead of anumber?
I see what you did there with
<invalid user to del>. You cheeky people :) (This was the only client-side check I had to do)
A pretty fun assignment, considering I beat the time to complete given by
Catalin(just 7.5 hrs instead of 12!)This assignment made me appreciate the tools given to us by standard libraries like in
Javascript / Node.js, also no, I would not want to send HTTP requests by hand again.This assignment gets a
10/10from me!