All Projects → fabiomaia → cantina

fabiomaia / cantina

Licence: other
🍔 Stupid web application that checks if the food at my university's canteens is good.

Programming Languages

javascript
184084 projects - #8 most used programming language
HTML
75241 projects
CSS
56736 projects

Projects that are alternatives of or similar to cantina

Vue Music
Music Player for Vue.js
Stars: ✭ 324 (+980%)
Mutual labels:  jsonp
Dbwebapi
(Migrated from CodePlex) DbWebApi is a .Net library that implement an entirely generic Web API (RESTful) for HTTP clients to call database (Oracle & SQL Server) stored procedures or functions in a managed way out-of-the-box without any configuration or coding.
Stars: ✭ 84 (+180%)
Mutual labels:  jsonp
Instagram Proxy Api
CORS compliant API to access Instagram's public data
Stars: ✭ 245 (+716.67%)
Mutual labels:  jsonp
Jsonpcallbackvalidator
JSONP callback validator.
Stars: ✭ 595 (+1883.33%)
Mutual labels:  jsonp
Vue Music
使用vue2.0构建音乐播放器
Stars: ✭ 60 (+100%)
Mutual labels:  jsonp
Render
Go package for easily rendering JSON, XML, binary data, and HTML templates responses.
Stars: ✭ 1,562 (+5106.67%)
Mutual labels:  jsonp
jekyll-rest-api
Read-only REST API for Jekyll, making it easy to fetch all posts/settings in JSON for javascript search or advanced queries.
Stars: ✭ 18 (-40%)
Mutual labels:  jsonp
leaflet-layerJSON
Build dynamic JSON Layer via Ajax/JSONP with caching
Stars: ✭ 82 (+173.33%)
Mutual labels:  jsonp
Jsonp
Java API for JSON Processing (JSON-P)
Stars: ✭ 77 (+156.67%)
Mutual labels:  jsonp
Renderer
Simple, lightweight and faster response (JSON, JSONP, XML, YAML, HTML, File) rendering package for Go
Stars: ✭ 220 (+633.33%)
Mutual labels:  jsonp
Fetch Jsonp
Make JSONP request like window.fetch
Stars: ✭ 932 (+3006.67%)
Mutual labels:  jsonp
Java Sec Code
Java web common vulnerabilities and security code which is base on springboot and spring security
Stars: ✭ 1,033 (+3343.33%)
Mutual labels:  jsonp
Seniverse Api Demos
心知天气 API 产品使用调用示例
Stars: ✭ 201 (+570%)
Mutual labels:  jsonp
Cross Origin
🌀 跨域demo。CORS、JSONP、postMessage、websocket、document.domain、window.name、iframe等示例
Stars: ✭ 475 (+1483.33%)
Mutual labels:  jsonp
ljq vue music
vue2 + vue-router2 +vuex + jsonp + es6 +webpack 抓取QQ音乐真实数据的移动端音乐WebApp
Stars: ✭ 43 (+43.33%)
Mutual labels:  jsonp
Reqwest
browser asynchronous http requests
Stars: ✭ 2,918 (+9626.67%)
Mutual labels:  jsonp
Restler
Simple and effective multi-format Web API Server to host your PHP API as Pragmatic REST and / or RESTful API
Stars: ✭ 1,324 (+4313.33%)
Mutual labels:  jsonp
AjaxHandler
ASimple PHP Class to help handling Ajax Requests easily
Stars: ✭ 30 (+0%)
Mutual labels:  jsonp
miniAjax
🚀A mini Ajax library provides Ajax, jsonp and ready features for simple web applications.
Stars: ✭ 67 (+123.33%)
Mutual labels:  jsonp
Json Viewer
It is a Chrome extension for printing JSON and JSONP.
Stars: ✭ 2,585 (+8516.67%)
Mutual labels:  jsonp

cantina

Stupid web application that checks if the next meal's food at the University of Aveiro's canteens is good.

https://fabiomaia.github.io/cantina/

cantina

Problem

Cross-domain AJAX requests are forbidden in the browser by the same-origin security policy. The API made available by the university does not allow cross-origin requests via CORS, so I can't just directly hit the API from the browser. Furthermore, since the university's API is served over HTTP, serving this application over HTTPS would throw mixed-content errors in most modern browsers.

Solutions

CORS

One solution is to run a proxy server-side that hits the API for me and serve it over HTTPS on an endpoint that accepts CORS requests. However, this requires a budget for server bills as well as maintenance upkeep to ensure the proxy is still running, which I am not willing to provide for such a stupid application.

There are CORS proxies available as a service that will proxy our request and serve it over HTTPS and CORS for free. In practice this means that instead of requesting

http://services.web.ua.pt/sas/ementas?date=day&format=json

we can instead simply request

https://cors.io/?http://services.web.ua.pt/sas/ementas?date=day&format=json

CORS is the modern and recommended solution for running cross-origin requests.

JSONP

Alternatively JSONP is an older technique that precedes CORS that is useful in rare scenarios where you need to support old browsers and only need to mimic read-only GET requests (not POST or PUT which it inherently cannot do).

Fundamentally it takes advantage of the fact that you can always embed arbitrary cross-domain scripts in a page, e.g.

<script src="http://services.web.ua.pt/sas/ementas?date=day&format=jsonp&cb=updateAnswer"></script>

If instead of a typical JSON-encoded HTTP response like

{"@attributes":{"request":"\/sas\/ementas","request_timestamp":"1564579826"},"menus":{"@attributes":{"zone":"santiago","type":"day"},"menu":[{"@attributes":{"canteen":"Refeit\u00f3rio de Santiago","meal":"Almo\u00e7o","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"Encerrado - refei\u00e7\u00f5es servidas no refeit\u00f3rio do crasto"},"items":{}},{"@attributes":{"canteen":"Refeit\u00f3rio de Santiago","meal":"Jantar","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"Encerrado - refei\u00e7\u00f5es servidas no refeit\u00f3rio do crasto"},"items":{}},{"@attributes":{"canteen":"Refeit\u00f3rio do Crasto","meal":"Almo\u00e7o","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"0"},"items":{"item":["Sopa de nabi\u00e7as","Bife de peru grelhado e batata cozida","Arroz de marisco","Cozido simples","Badejo cozido com batata cozida e feij\u00e3o verde","Fruta da \u00e9poca ou doce","Buffet de saladas",{"@attributes":{"name":"Diversos"}},"P\u00e3o de mistura"]}},{"@attributes":{"canteen":"Refeit\u00f3rio do Crasto","meal":"Jantar","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"0"},"items":{"item":["Sopa de nabi\u00e7as","Frango estufado com arroz de ervilhas",{"@attributes":{"name":"Prato normal peixe"}},"Seitan de cebolada",{"@attributes":{"name":"Prato vegetariano"}},{"@attributes":{"name":"Prato op\u00e7\u00e3o"}},"Buffet de saladas","P\u00e3o de mistura","Fruta da \u00e9poca ou doce"]}},{"@attributes":{"canteen":"Snack-Bar\/Self","meal":"Almo\u00e7o","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"0"},"items":{"item":["Sopa de nabi\u00e7as","Arroz de aves","Espadarte grelhado com molho de mostarda e batata cozida","Buffet de saladas","Cozido simples","Fruta da \u00e9poca ou doce",{"@attributes":{"name":"Bebida"}}]}}]}})

the remote server instead wraps up the HTTP response in a callback function updateAnswer (presumably defined before the embedded script is run) such that it forms valid JavaScript code

updateAnswer({"@attributes":{"request":"\/sas\/ementas","request_timestamp":"1564579826"},"menus":{"@attributes":{"zone":"santiago","type":"day"},"menu":[{"@attributes":{"canteen":"Refeit\u00f3rio de Santiago","meal":"Almo\u00e7o","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"Encerrado - refei\u00e7\u00f5es servidas no refeit\u00f3rio do crasto"},"items":{}},{"@attributes":{"canteen":"Refeit\u00f3rio de Santiago","meal":"Jantar","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"Encerrado - refei\u00e7\u00f5es servidas no refeit\u00f3rio do crasto"},"items":{}},{"@attributes":{"canteen":"Refeit\u00f3rio do Crasto","meal":"Almo\u00e7o","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"0"},"items":{"item":["Sopa de nabi\u00e7as","Bife de peru grelhado e batata cozida","Arroz de marisco","Cozido simples","Badejo cozido com batata cozida e feij\u00e3o verde","Fruta da \u00e9poca ou doce","Buffet de saladas",{"@attributes":{"name":"Diversos"}},"P\u00e3o de mistura"]}},{"@attributes":{"canteen":"Refeit\u00f3rio do Crasto","meal":"Jantar","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"0"},"items":{"item":["Sopa de nabi\u00e7as","Frango estufado com arroz de ervilhas",{"@attributes":{"name":"Prato normal peixe"}},"Seitan de cebolada",{"@attributes":{"name":"Prato vegetariano"}},{"@attributes":{"name":"Prato op\u00e7\u00e3o"}},"Buffet de saladas","P\u00e3o de mistura","Fruta da \u00e9poca ou doce"]}},{"@attributes":{"canteen":"Snack-Bar\/Self","meal":"Almo\u00e7o","date":"Wed, 31 Jul 2019 14:30:01 +0100","weekday":"Wednesday","weekdayNr":"3","disabled":"0"},"items":{"item":["Sopa de nabi\u00e7as","Arroz de aves","Espadarte grelhado com molho de mostarda e batata cozida","Buffet de saladas","Cozido simples","Fruta da \u00e9poca ou doce",{"@attributes":{"name":"Bebida"}}]}}]}})

then one can embed this script and trigger the updateAnswer function call (with the data that we wanted to obtain) which can finally process the data arbitrarily. In essence this is equivalent to requesting the resource as originally intended, and is effectively circumnavigating the same-origin security policy.

Programatically,

function updateAnswer(json) {
    // ...
}

function getJSONP(url, param, cb) {
    const script = document.createElement('script')
    script.src = `${url}&${param}=${cb.name}`
    document.querySelector('head').appendChild(script)
}

getJSONP('http://services.web.ua.pt/sas/ementas?date=day&format=jsonp&cb=updateAnswer', 'cb', updateAnswer)

Embedded scripts are likely to be cached by the browser though. You may want to force a fresh request each time by appending something unique to the query string (e.g. the current Unix timestamp) to invalidate the cache.

function getJSONP(url, param, cb) {
    const script = document.createElement('script')
    script.src = `${url}&${param}=${cb.name}&v=${Date.now()}`
    document.querySelector('head').appendChild(script)
}
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].