recalapp / recal

First a COS 333 project, now a very popular tool at Princeton for course selection
http://recal.io
MIT License
12 stars 3 forks source link

Cannot save schedule on Safari #326

Closed maximz closed 6 years ago

maximz commented 7 years ago

Seems related to #11 but different. On Safari Version 10.0.3 on Mac, I've observed the following behavior:

  1. Add a class to a schedule.
  2. Refresh
  3. Class is no longer there.

But you can create a new schedule without issue (i.e. it survives refresh).

The issue affects all semester. The behavior is not present when ReCal is used in Firefox on the same machine. Unclear if this happens on all Safari installs -- I have not tried to reproduce on other machines. On the machine that has this issue, this happens in both Safari normal and private browsing modes. According to the bug reporter, this only started happening recently.

Safari Web Inspector shows a Failed to load resource: the server responded with a status of 400 (BAD REQUEST) error at http://recal.io/course_selection/api/v1/schedule/[id]/.

Example request to http://recal.io/course_selection/api/v1/schedule/30985/, a schedule titled "good":

{"available_colors":"[{\"dark\":\"#2D6234\",\"id\":1,\"light\":\"#D0DECF\",\"resource_uri\":\"/api/v1/color_palette/1/\"},{\"dark\":\"#385C92\",\"id\":2,\"light\":\"#d5dcec\",\"resource_uri\":\"/api/v1/color_palette/2/\"},{\"dark\":\"#954962\",\"id\":3,\"light\":\"#ebd2db\",\"resource_uri\":\"/api/v1/color_palette/3/\"},{\"dark\":\"#b17f00\",\"id\":4,\"light\":\"#faf4cb\",\"resource_uri\":\"/api/v1/color_palette/4/\"},{\"dark\":\"#895e2e\",\"id\":5,\"light\":\"#e7dcce\",\"resource_uri\":\"/api/v1/color_palette/5/\"},{\"dark\":\"#2f7770\",\"id\":6,\"light\":\"#d1e7e4\",\"resource_uri\":\"/api/v1/color_palette/6/\"},{\"dark\":\"#614996\",\"id\":7,\"light\":\"#dcd5e2\",\"resource_uri\":\"/api/v1/color_palette/7/\"}]","enrollments":"[{\"course_id\":3825,\"color\":{\"dark\":\"#2f7770\",\"id\":6,\"light\":\"#d1e7e4\",\"resource_uri\":\"/api/v1/color_palette/6/\"},\"sections\":[9051]},{\"course_id\":4224,\"color\":{\"dark\":\"#385C92\",\"id\":2,\"light\":\"#d5dcec\",\"resource_uri\":\"/api/v1/color_palette/2/\"},\"sections\":[9942]}]","ical_uuid":"2983daef-e679-441c-87ad-5ed7e844df30","id":30985,"resource_uri":"/api/v1/schedule/30985/","semester":{"end_date":"2017-06-06","id":25,"name":"16-17 Spring","resource_uri":"/api/v1/semester/25/","start_date":"2017-02-06","term_code":"1174"},"title":"good","user":"/api/v1/user/1689/"}

Example response:

{
    "error": "Request is not valid JSON."
}

But this looks like valid JSON to me! Prettified version:

{
    "available_colors": "[{\"dark\":\"#2D6234\",\"id\":1,\"light\":\"#D0DECF\",\"resource_uri\":\"/api/v1/color_palette/1/\"},{\"dark\":\"#385C92\",\"id\":2,\"light\":\"#d5dcec\",\"resource_uri\":\"/api/v1/color_palette/2/\"},{\"dark\":\"#954962\",\"id\":3,\"light\":\"#ebd2db\",\"resource_uri\":\"/api/v1/color_palette/3/\"},{\"dark\":\"#b17f00\",\"id\":4,\"light\":\"#faf4cb\",\"resource_uri\":\"/api/v1/color_palette/4/\"},{\"dark\":\"#895e2e\",\"id\":5,\"light\":\"#e7dcce\",\"resource_uri\":\"/api/v1/color_palette/5/\"},{\"dark\":\"#2f7770\",\"id\":6,\"light\":\"#d1e7e4\",\"resource_uri\":\"/api/v1/color_palette/6/\"},{\"dark\":\"#614996\",\"id\":7,\"light\":\"#dcd5e2\",\"resource_uri\":\"/api/v1/color_palette/7/\"}]",
    "enrollments": "[{\"course_id\":3825,\"color\":{\"dark\":\"#2f7770\",\"id\":6,\"light\":\"#d1e7e4\",\"resource_uri\":\"/api/v1/color_palette/6/\"},\"sections\":[9051]},{\"course_id\":4224,\"color\":{\"dark\":\"#385C92\",\"id\":2,\"light\":\"#d5dcec\",\"resource_uri\":\"/api/v1/color_palette/2/\"},\"sections\":[9942]}]",
    "ical_uuid": "2983daef-e679-441c-87ad-5ed7e844df30",
    "id": 30985,
    "resource_uri": "/api/v1/schedule/30985/",
    "semester": {
        "end_date": "2017-06-06",
        "id": 25,
        "name": "16-17 Spring",
        "resource_uri": "/api/v1/semester/25/",
        "start_date": "2017-02-06",
        "term_code": "1174"
    },
    "title": "good",
    "user": "/api/v1/user/1689/"
}

Also seeing some SyntaxError: Unexpected identifier 'Object'. Expected either a closing ']' or a ',' following an array element. (anonymous function) — recal.io:1, but seems to happen on page load before adding a course. Regrettably, Safari can't point to the exact line.

In Chrome, I see no errors at all on the page.

(H/T Yash Patel for alerting to the bug)

@naphatkrit @dxue2012 any thoughts?

panchr commented 6 years ago

Isolated the cause of this issue: Safari is setting the Content-Length to 0, which means the server ignores the body. This only seems to be happening on PUT requests (and the action of editing a schedule is the only PUT request used on the API).

Reproduced error in curl:

$ curl 'http://recal.io/course_selection/api/v1/schedule/53228/' \
> -XPUT \
> -H 'Referer: http://recal.io/' \
> -H 'Content-Type: application/json;charset=UTF-8' \
> -H 'Origin: http://recal.io' \
> -H 'Host: recal.io' \
> -H 'Accept: application/json, text/plain, */*' \
> -H 'Connection: keep-alive' \
> -H 'Accept-Encoding: gzip, deflate' \
> -H 'Accept-Language: en-us' \
> -H 'DNT: 1' \
> -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5' \
> -H 'Cookie: csrftoken=$TOKEN; sessionid=$SESSIONID; __cfduid=$CFID' \
> -H 'Content-Length: 0' \
> --data-binary '{"available_colors":"[{\"light\":\"#d5dcec\",\"dark\":\"#385C92\",\"id\":0},{\"light\":\"#e7dcce\",\"dark\":\"#895e2e\",\"id\":0},{\"light\":\"#d1e7e4\",\"dark\":\"#2f7770\",\"id\":0},{\"light\":\"#ebd2db\",\"dark\":\"#954962\",\"id\":0},{\"light\":\"#D0DECF\",\"dark\":\"#2D6234\",\"id\":0},{\"light\":\"#faf4cb\",\"dark\":\"#b17f00\",\"id\":4},{\"light\":\"#dcd5e2\",\"dark\":\"#614996\",\"id\":0}]","enrollments":"[{\"course_id\":6654,\"color\":{\"light\":\"#d5dcec\",\"dark\":\"#385C92\",\"id\":0},\"sections\":[15578]},{\"course_id\":7425,\"color\":{\"light\":\"#ebd2db\",\"dark\":\"#954962\",\"id\":0},\"sections\":[17073]}]","ical_uuid":"d7494f0a-7768-4a5f-b231-829c079fbe9e","id":53228,"resource_uri":"/api/v1/schedule/53228/","semester":{"end_date":"2018-06-05","id":42,"name":"17-18 Spring","resource_uri":"/api/v1/semester/42/","start_date":"2018-02-05","term_code":"1184"},"title":"First Plan","user":"/api/v1/user/2525/"}'
{"error": "Request is not valid JSON."}

Note the Content-Length: 0 header. Setting it to the correct value (in this case, 934) allows proper submission. A possible solution may be to change this endpoint to using POST requests and then ensuring that those requests are treated as idempotent (if they contain a primary key), which is what PUT does... however, that violates the HTTP standard so a better solution is preferred. The Resource that generates the requests is created here: https://github.com/recalapp/recal/blob/master/course_selection/static/js/services/ResourceBuilder.ts#L49.

maximz commented 6 years ago

Thank you for your excellent work, @panchr

sebthedev commented 6 years ago

Thank you so much for fixing this, @panchr!