Cross-Origin Resource Sharing

תקשורת בקליינט סייד בין דומיינים שונים בקלות. אפילו עם אקספלורר.
בדיקת headers בכלי הפיתוח של גוגל כרום

Cross-Origin Resource Sharing או CORS היא דרך מודרנית ובטוחה לאפשר בקשות AJAX בין שני דומיינים. במאמר זה אני אסביר מעט על הדרך הזו, איך היא עובדת ואיך אפשר באמצעותה להעביר מידע מדף שיושב בדומיין A לדף שיושב בדומיין B.

היסטוריה קצרה למי שצריך – כאשר יש לי בקשת AJAX מאינטרנט ישראל (למשל) לדומיין אחר כמו http://api.icndb.com, באופן טבעי הדפדפן לא יאפשר את הבקשה הזו מסיבות אבטחה. למשל על מנת למנוע מתקפות Phishing. מפתח שניסה לממש קריאה לדומיין אחר היה מגלה שהקריאה נחסמה.
היו מגוון שיטות לעקוף את החסימה – שימוש בפרוקסי, שימוש במעקף מוזר של פלאש וכמובן JSONP. על כולן כתבתי פה, אבל מותו של אינטרנט אקספלורר 7 פתח את הדרך למימוש של דרכים יותר נורמליות לעבודה בין שני דומיינים שונים.

איך זה עובד? בגדול זה תלוי במימוש שלכם ובשרת המרוחק – השרת המרוחק חייב להחזיר header שנראה ככה:

Access-Control-Allow-Origin: *

למי שלא יודע, בכל בקשת מידע דרך פרוטוקול http, אנו מקבלים headers שונים ומשונים. על מנת לראות את ה-header של השרת, אנו זקוקים לכלי מפתחים. פיירבאג או כרום dev tools הם כלים מספיקים. נכנס לדף שאליו אנו רוצים לבצע את הקריאה, למשל http://api.icndb.com/jokes/random. נפתח את כלי המפתחים, נלחץ על לשונית Net בפיירבאג או Network בכרום, נבחר ב-Headers ונוכל לראות שיש header מתאים של
Access-Control-Allow-Origin: *.

בדיקת headers בכלי הפיתוח של גוגל כרום
בדיקת headers בכלי הפיתוח של גוגל כרום
בדיקת headers בפיירבאג
בדיקת headers בפיירבאג

הכוכבית מסמלת שכל דומיין יכול לקבל בקשה של cross domain. כמובן שלא חייבים כוכבית אלא אפשר לשים שם שמות של דומיינים ספציפיים.

איך דואגים לזה בצד השרת? בקלות. אפשר לעשות את זה בהגדרות פשוטות ביותר בכל שרת אינטרנט. אם אין לכם גישה לשרת, מדובר במשהו שגם קל לעשות באפליקציה עצמה – תלוי באיזו שפה אתם משתמשים כמובן. באתר הזה יש הסברים על איך מאפשרים CORS במגוון שפות שונות ובמגוון שרתים שונים.

בצד הלקוח? זה גם פשוט, אם אתם משתמשים בדפדפן מודרני – כל מה שצריך לעשות זה לבצע קריאת AJAX רגילה. ככה עושים את זה באופן הכי פשוט שאפשר:

    req.open('GET', 'http://api.icndb.com/jokes/random', true);
    // Just like regular ol' XHR
    req.onreadystatechange = function() {
        if (req.readyState === 4) {
            if (req.status >= 200 && req.status < 400) {
              var response = JSON.parse(req.response);
              console.log(response.value.joke);
            } else {
                // Handle error case
            }
        }
    };
    req.send();

אבל אנחנו לא חיים בעולם מושלם אלא בעולם שיש בו גם את דפדפן השטן, באופן עקרוני אינטרנט אקספלורר 11 תומך ב-CORS באופן מלא כמעט כמו כל דפדפן מודרני. התפלצות מגרסת 8-10 יכולים באופן עקרוני לתמוך בזה באמצעות אימפלמנטציה לא תקנית של CORS כמיטב המסורת של מיקרוסופט. איך עושים את זה? מבצעים feature detection פשוט לתמיכה ב-CORS. במידה ואין תמיכה, מבצעים את האימפלמנטציה המיקרוסופטית המוזרה:

var req = new XMLHttpRequest();

// Feature detection for CORS
if (!('withCredentials' in req) && typeof XDomainRequest != "undefined") {
  req = new XDomainRequest();
}
req.open('GET', 'http://api.icndb.com/jokes/random', true);
// Just like regular ol' XHR
req.onreadystatechange = function() {
  if (req.readyState === 4) {
    if (req.status >= 200 && req.status < 400) {
      var response = JSON.parse(req.response);
      console.log(response.value.joke);
    } else {
      // Handle error case
    }
  }
};
req.send();

מה בעצם הלך פה? אם אני רואה שאין לי withCredentials אבל כן יש לי אובייקט שנקרא XDomainRequest, סימן שמדובר בתפלצת מיקרוסופטית שצריכה טיפול מיוחד. במקרה הזה הטיפול המיוחד נעשה על ידי הגדרת אובייקט XHR נפרד. לא ביג דיל, סתם משהו מעצבן.

חשוב להדגיש שגם אם אתם נמצאים ב-https, לא תצליחו ליצור קשר עם http גם באמצעות CORS.

פוסטים נוספים שכדאי לקרוא

גלילה לראש העמוד