Freigeben über


Lernprogramm: Erstellen einer einzelseitigen App mithilfe der Bing Web Search-API

Warnung

Am 30. Oktober 2020 wurden die Bing Search-APIs von Azure AI-Diensten zu Bing Search Services verschoben. Diese Dokumentation wird nur zur Referenz bereitgestellt. Eine aktualisierte Dokumentation finden Sie in der Dokumentation zu den Bing-Suche-APIs. Anweisungen zum Erstellen neuer Azure-Ressourcen für die Bing-Suche finden Sie unter Erstellen einer Ressource für die Bing-Suche über Azure Marketplace.

Diese Einzelseiten-App veranschaulicht, wie Suchergebnisse aus der Bing Web Search-API abgerufen, analysiert und angezeigt werden. Das Lernprogramm verwendet Codebausteine HTML und CSS und konzentriert sich auf den JavaScript-Code. HTML-, CSS- und JS-Dateien sind auf GitHub- mit Schnellstartanweisungen verfügbar.

Diese Beispiel-App kann:

  • Aufrufen der Bing Web Search-API mit Suchoptionen
  • Anzeigen von Web-, Bild-, Nachrichten- und Videoergebnissen
  • Ergebnisse paginieren
  • Abonnementschlüssel verwalten
  • Fehler behandeln

Um diese App zu verwenden, ist ein Azure AI Services-Konto mit Bing Search-APIs erforderlich.

Voraussetzungen

Hier sind einige Dinge, die Sie zum Ausführen der App benötigen:

Der erste Schritt besteht darin, das Repository mit dem Quellcode der Beispiel-App zu klonen.

git clone https://github.com/Azure-Samples/cognitive-services-REST-api-samples.git

Führen Sie dann npm installaus. In diesem Lernprogramm ist Express.js die einzige Abhängigkeit.

cd <path-to-repo>/cognitive-services-REST-api-samples/Tutorials/bing-web-search
npm install

App-Komponenten

Die Beispiel-App, die wir erstellen, besteht aus vier Teilen:

  • bing-web-search.js – Unsere Express.js-App. Er verarbeitet Anforderungs-/Antwortlogik und Routing.
  • public/index.html - Das Skelett unserer App; es definiert, wie Daten dem Benutzer präsentiert werden.
  • public/css/styles.css – Definiert Seitenformatvorlagen, z. B. Schriftarten, Farben, Textgröße.
  • public/js/scripts.js – Enthält die Logik zum Senden von Anforderungen an die Bing Web Search-API, zum Verwalten von Abonnementschlüsseln, zum Verarbeiten und Analysieren von Antworten und zum Anzeigen von Ergebnissen.

Dieses Lernprogramm konzentriert sich auf scripts.js und die Logik, die zum Aufrufen der Bing Web Search-API und zum Behandeln der Antwort erforderlich ist.

HTML-Formular

Die index.html enthält ein Formular, mit dem Benutzer Suchoptionen durchsuchen und auswählen können. Das attribut onsubmit wird ausgelöst, wenn das Formular gesendet wird und die in scripts.jsdefinierte bingWebSearch() Methode aufruft. Es werden drei Argumente verwendet:

  • Suchabfrage
  • Ausgewählte Optionen
  • Abonnementschlüssel
<form name="bing" onsubmit="return bingWebSearch(this.query.value,
    bingSearchOptions(this), getSubscriptionKey())">

Abfrageoptionen

Das HTML-Formular enthält Optionen, die Abfrageparametern in der Bing Web Search API v7zugeordnet sind. Diese Tabelle enthält eine Übersicht darüber, wie Benutzer Suchergebnisse mithilfe der Beispiel-App filtern können:

Parameter BESCHREIBUNG
query Ein Textfeld zum Eingeben einer Abfragezeichenfolge.
where Ein Dropdownmenü zum Auswählen des Marktes (Standort und Sprache).
what Kontrollkästchen zur Förderung bestimmter Ergebnistypen. Das Bewerben von Bildern erhöht z. B. die Rangfolge von Bildern in Suchergebnissen.
when Ein Dropdownmenü, mit dem der Benutzer die Suchergebnisse auf heute, diese Woche oder diesen Monat beschränken kann.
safe Ein Kontrollkästchen zum Aktivieren von Bing SafeSearch, das erwachsene Inhalte herausfiltert.
count Ausgeblendetes Feld. Die Anzahl der Suchergebnisse, die für jede Anforderung zurückgegeben werden sollen. Ändern Sie diesen Wert, um weniger oder mehr Ergebnisse pro Seite anzuzeigen.
offset Ausgeblendetes Feld. Der Offset des ersten Suchergebnisses in der Anforderung, der für das Paging verwendet wird. Sie wird bei jeder neuen Anforderung auf 0 zurückgesetzt.

Hinweis

Die Bing Web Search-API bietet zusätzliche Abfrageparameter, um Suchergebnisse zu verfeinern. In diesem Beispiel werden nur einige verwendet. Eine vollständige Liste der verfügbaren Parameter finden Sie unter Bing Web Search API v7 Reference.

Die bingSearchOptions()-Funktion konvertiert diese Optionen entsprechend dem format, das von der Bing Search-API benötigt wird.

// Build query options from selections in the HTML form.
function bingSearchOptions(form) {

    var options = [];
    // Where option.
    options.push("mkt=" + form.where.value);
    // SafeSearch option.
    options.push("SafeSearch=" + (form.safe.checked ? "strict" : "moderate"));
    // Freshness option.
    if (form.when.value.length) options.push("freshness=" + form.when.value);
    var what = [];
    for (var i = 0; i < form.what.length; i++)
        if (form.what[i].checked) what.push(form.what[i].value);
    // Promote option.
    if (what.length) {
        options.push("promote=" + what.join(","));
        options.push("answerCount=9");
    }
    // Count option.
    options.push("count=" + form.count.value);
    // Offset option.
    options.push("offset=" + form.offset.value);
    // Hardcoded text decoration option.
    options.push("textDecorations=true");
    // Hardcoded text format option.
    options.push("textFormat=HTML");
    return options.join("&");
}

SafeSearch kann auf strict, moderateoder offfestgelegt werden, wobei moderate die Standardeinstellung für Bing Web Search ist. Dieses Formular verwendet ein Kontrollkästchen mit zwei Zuständen: strict oder moderate.

Wenn eines der Kontrollkästchen "Höherstufen" aktiviert ist, wird der Abfrage der parameter answerCount hinzugefügt. answerCount ist bei Verwendung des promote Parameters erforderlich. In diesem Codeausschnitt wird der Wert auf 9 festgelegt, um alle verfügbaren Ergebnistypen zurückzugeben.

Hinweis

Das Bewerben eines Ergebnistyps garantiert nicht , dass er in die Suchergebnisse einbezogen wird. Stattdessen erhöht die Werbung die Rangfolge dieser Arten von Ergebnissen relativ zu ihrer üblichen Rangfolge. Um Suchvorgänge auf bestimmte Arten von Ergebnissen zu beschränken, verwenden Sie den responseFilter Abfrageparameter, oder rufen Sie einen spezifischeren Endpunkt wie Bing Image Search oder Bing News Search auf.

Die abfrageparameter textDecoration und textFormat werden in das Skript hartcodiert und bewirken, dass der Suchbegriff in den Suchergebnissen fett formatiert wird. Diese Parameter sind nicht erforderlich.

Abonnementschlüssel verwalten

Um die Hardcodierung des Bing Search API-Abonnementschlüssels zu vermeiden, verwendet diese Beispiel-App den persistenten Speicher eines Browsers, um den Abonnementschlüssel zu speichern. Wenn kein Abonnementschlüssel gespeichert ist, wird der Benutzer aufgefordert, einen Schlüssel einzugeben. Wenn der Abonnementschlüssel von der API abgelehnt wird, wird der Benutzer aufgefordert, einen Abonnementschlüssel erneut einzugeben.

Die getSubscriptionKey()-Funktion verwendet die funktionen storeValue und retrieveValue zum Speichern und Abrufen des Abonnementschlüssels eines Benutzers. Diese Funktionen verwenden das localStorage-Objekt, sofern unterstützt oder Cookies.

// Cookie names for stored data.
API_KEY_COOKIE   = "bing-search-api-key";
CLIENT_ID_COOKIE = "bing-search-client-id";

BING_ENDPOINT = "https://api.cognitive.microsoft.com/bing/v7.0/search";

// See source code for storeValue and retrieveValue definitions.

// Get stored subscription key, or prompt if it isn't found.
function getSubscriptionKey() {
    var key = retrieveValue(API_KEY_COOKIE);
    while (key.length !== 32) {
        key = prompt("Enter Bing Search API subscription key:", "").trim();
    }
    // Always set the cookie in order to update the expiration date.
    storeValue(API_KEY_COOKIE, key);
    return key;
}

Wie wir bereits gesehen haben, wird beim Übermitteln des Formulars onsubmit ausgelöst, wodurch bingWebSearchaufgerufen wird. Diese Funktion initialisiert und sendet die Anforderung. getSubscriptionKey wird für jede Übermittlung aufgerufen, um die Anforderung zu authentifizieren.

Angesichts der Abfrage, der Optionszeichenfolge und des Abonnementschlüssels erstellt die BingWebSearch-Funktion ein XMLHttpRequest Objekt, um den Bing Web Search-Endpunkt aufzurufen.

// Perform a search constructed from the query, options, and subscription key.
function bingWebSearch(query, options, key) {
    window.scrollTo(0, 0);
    if (!query.trim().length) return false;

    showDiv("noresults", "Working. Please wait.");
    hideDivs("pole", "mainline", "sidebar", "_json", "_http", "paging1", "paging2", "error");

    var request = new XMLHttpRequest();
    var queryurl = BING_ENDPOINT + "?q=" + encodeURIComponent(query) + "&" + options;

    // Initialize the request.
    try {
        request.open("GET", queryurl);
    }
    catch (e) {
        renderErrorMessage("Bad request (invalid URL)\n" + queryurl);
        return false;
    }

    // Add request headers.
    request.setRequestHeader("Ocp-Apim-Subscription-Key", key);
    request.setRequestHeader("Accept", "application/json");
    var clientid = retrieveValue(CLIENT_ID_COOKIE);
    if (clientid) request.setRequestHeader("X-MSEdge-ClientID", clientid);

    // Event handler for successful response.
    request.addEventListener("load", handleBingResponse);

    // Event handler for errors.
    request.addEventListener("error", function() {
        renderErrorMessage("Error completing request");
    });

    // Event handler for an aborted request.
    request.addEventListener("abort", function() {
        renderErrorMessage("Request aborted");
    });

    // Send the request.
    request.send();
    return false;
}

Nach einer erfolgreichen Anforderung wird der Ereignishandler load aktiviert und ruft die Funktion handleBingResponse auf. handleBingResponse analysiert das Ergebnisobjekt, zeigt die Ergebnisse an und enthält Fehlerlogik für fehlgeschlagene Anforderungen.

function handleBingResponse() {
    hideDivs("noresults");

    var json = this.responseText.trim();
    var jsobj = {};

    // Try to parse results object.
    try {
        if (json.length) jsobj = JSON.parse(json);
    } catch(e) {
        renderErrorMessage("Invalid JSON response");
        return;
    }

    // Show raw JSON and the HTTP request.
    showDiv("json", preFormat(JSON.stringify(jsobj, null, 2)));
    showDiv("http", preFormat("GET " + this.responseURL + "\n\nStatus: " + this.status + " " +
        this.statusText + "\n" + this.getAllResponseHeaders()));

    // If the HTTP response is 200 OK, try to render the results.
    if (this.status === 200) {
        var clientid = this.getResponseHeader("X-MSEdge-ClientID");
        if (clientid) retrieveValue(CLIENT_ID_COOKIE, clientid);
        if (json.length) {
            if (jsobj._type === "SearchResponse" && "rankingResponse" in jsobj) {
                renderSearchResults(jsobj);
            } else {
                renderErrorMessage("No search results in JSON response");
            }
        } else {
            renderErrorMessage("Empty response (are you sending too many requests too quickly?)");
        }
    }

    // Any other HTTP response is considered an error.
    else {
        // 401 is unauthorized; force a re-prompt for the user's subscription
        // key on the next request.
        if (this.status === 401) invalidateSubscriptionKey();

        // Some error responses don't have a top-level errors object, if absent
        // create one.
        var errors = jsobj.errors || [jsobj];
        var errmsg = [];

        // Display the HTTP status code.
        errmsg.push("HTTP Status " + this.status + " " + this.statusText + "\n");

        // Add all fields from all error responses.
        for (var i = 0; i < errors.length; i++) {
            if (i) errmsg.push("\n");
            for (var k in errors[i]) errmsg.push(k + ": " + errors[i][k]);
        }

        // Display Bing Trace ID if it isn't blocked by CORS.
        var traceid = this.getResponseHeader("BingAPIs-TraceId");
        if (traceid) errmsg.push("\nTrace ID " + traceid);

        // Display the error message.
        renderErrorMessage(errmsg.join("\n"));
    }
}

Wichtig

Eine erfolgreiche HTTP-Anforderung bedeutet nicht, dass die Suche selbst erfolgreich war. Wenn im Suchvorgang ein Fehler auftritt, gibt die Bing Web Search-API einen NICHT-200 HTTP-Statuscode zurück und enthält Fehlerinformationen in der JSON-Antwort. Wenn die Anforderung rate-begrenzt war, gibt die API eine leere Antwort zurück.

Ein Großteil des Codes in beiden vorherigen Funktionen ist der Fehlerbehandlung gewidmet. Fehler können in den folgenden Phasen auftreten:

Etappe Potenzieller Fehler(n) Behandelt von
Erstellen des Anforderungsobjekts Ungültige URL try / catch Block
Erstellen der Anfrage Netzwerkfehler, abgebrochene Verbindungen error und abort Ereignishandler
Durchführen der Suche Ungültige Anforderung, ungültiges JSON, Ratelimits Tests im load Ereignishandler

Fehler werden durch das Aufrufen von renderErrorMessage()behandelt. Wenn die Antwort alle Fehlertests bestanden hat, wird renderSearchResults() aufgerufen, um die Suchergebnisse anzuzeigen.

Anzeigen von Suchergebnissen

Es gibt Verwendungs- und Anzeigeanforderungen für Ergebnisse, die von der Bing Web Search-API zurückgegeben werden. Da eine Antwort möglicherweise verschiedene Ergebnistypen enthält, reicht es nicht aus, die Auflistung WebPages der obersten Ebene zu durchlaufen. Stattdessen verwendet die Beispiel-App RankingResponse, um die Ergebnisse gemäß Vorgaben anzuordnen.

Hinweis

Wenn Sie nur einen einzelnen Ergebnistyp verwenden möchten, verwenden Sie den responseFilter Abfrageparameter, oder erwägen Sie die Verwendung eines der anderen Bing Search-Endpunkte, z. B. Bing-Bildsuche.

Jede Antwort verfügt über ein RankingResponse-Objekt, das bis zu drei Auflistungen enthalten kann: pole, mainlineund sidebar. pole, falls vorhanden, ist das relevanteste Suchergebnis und muss deutlich angezeigt werden. mainline enthält die meisten Suchergebnisse und wird unmittelbar nach poleangezeigt. sidebar enthält zusätzliche Suchergebnisse. Wenn möglich, sollten diese Ergebnisse in der Randleiste angezeigt werden. Wenn Bildschirmbeschränkungen eine Randleiste unpraktisch machen, sollten diese Ergebnisse nach den mainline Ergebnissen angezeigt werden.

Jede RankingResponse enthält ein RankingItem Array, das angibt, wie Ergebnisse sortiert werden müssen. Unsere Beispiel-App verwendet die Parameter answerType und resultIndex, um das Ergebnis zu identifizieren.

Hinweis

Es gibt weitere Möglichkeiten zum Identifizieren und Bewerten von Ergebnissen. Weitere Informationen finden Sie unter Verwenden der Rangfolge zum Anzeigen von Ergebnissen.

Sehen wir uns den Code an:

// Render the search results from the JSON response.
function renderSearchResults(results) {

    // If spelling was corrected, update the search field.
    if (results.queryContext.alteredQuery)
        document.forms.bing.query.value = results.queryContext.alteredQuery;

    // Add Prev / Next links with result count.
    var pagingLinks = renderPagingLinks(results);
    showDiv("paging1", pagingLinks);
    showDiv("paging2", pagingLinks);

    // Render the results for each section.
    for (section in {pole: 0, mainline: 0, sidebar: 0}) {
        if (results.rankingResponse[section])
            showDiv(section, renderResultsItems(section, results));
    }
}

Die renderResultsItems()-Funktion durchläuft die Elemente in jeder RankingResponse-Auflistung, ordnet jedes Bewertungsergebnis einem Suchergebnis mithilfe der answerType und resultIndex Werte zu und ruft die entsprechende Renderingfunktion auf, um den HTML-Code zu generieren. Wenn resultIndex für ein Element nicht angegeben ist, durchläuft renderResultsItems() alle Ergebnisse dieses Typs und ruft die Renderingfunktion für jedes Element auf. Der resultierende HTML-Code wird in index.htmlin das entsprechende <div>-Element eingefügt.

// Render search results from the RankingResponse object per rank response and
// use and display requirements.
function renderResultsItems(section, results) {

    var items = results.rankingResponse[section].items;
    var html = [];
    for (var i = 0; i < items.length; i++) {
        var item = items[i];
        // Collection name has lowercase first letter while answerType has uppercase
        // e.g. `WebPages` RankingResult type is in the `webPages` top-level collection.
        var type = item.answerType[0].toLowerCase() + item.answerType.slice(1);
        if (type in results && type in searchItemRenderers) {
            var render = searchItemRenderers[type];
            // This ranking item refers to ONE result of the specified type.
            if ("resultIndex" in item) {
                html.push(render(results[type].value[item.resultIndex], section));
            // This ranking item refers to ALL results of the specified type.
            } else {
                var len = results[type].value.length;
                for (var j = 0; j < len; j++) {
                    html.push(render(results[type].value[j], section, j, len));
                }
            }
        }
    }
    return html.join("\n\n");
}

Überprüfen von Rendererfunktionen

In unserer Beispiel-App enthält das searchItemRenderers-Objekt Funktionen, die HTML für jeden Suchergebnistyp generieren.

// Render functions for each result type.
searchItemRenderers = {
    webPages: function(item) { ... },
    news: function(item) { ... },
    images: function(item, section, index, count) { ... },
    videos: function(item, section, index, count) { ... },
    relatedSearches: function(item, section, index, count) { ... }
}

Wichtig

Die Beispiel-App enthält Renderer für Webseiten, Nachrichten, Bilder, Videos und verwandte Suchvorgänge. Ihre Anwendung benötigt Renderer für jeden empfangenen Ergebnistyp, der Berechnungen, Rechtschreibvorschläge, Entitäten, Zeitzonen und Definitionen umfassen kann.

Einige der Renderingfunktionen akzeptieren nur den item Parameter. Andere akzeptieren zusätzliche Parameter, die verwendet werden können, um Elemente je nach Kontext unterschiedlich zu rendern. Ein Renderer, der diese Informationen nicht verwendet, muss diese Parameter nicht akzeptieren.

Die Kontextargumente sind:

Parameter BESCHREIBUNG
section Der Ergebnisabschnitt (pole, mainlineoder sidebar), in dem das Element angezeigt wird.
index
count
Verfügbar, wenn das RankingResponse Element angibt, dass alle Ergebnisse in einer bestimmten Auflistung angezeigt werden sollen; andernfalls undefined. Der Index des Elements innerhalb seiner Sammlung und die Gesamtanzahl der Elemente in dieser Sammlung. Sie können diese Informationen verwenden, um die Ergebnisse zu nummerieren, um unterschiedliche HTML-Code für das erste oder letzte Ergebnis usw. zu generieren.

In der Beispiel-App verwenden sowohl die images als auch relatedSearches Renderer die Kontextargumente, um den generierten HTML-Code anzupassen. Sehen wir uns den images Renderer genauer an:

searchItemRenderers = {
    // Render image result with thumbnail.
    images: function(item, section, index, count) {
        var height = 60;
        var width = Math.round(height * item.thumbnail.width / item.thumbnail.height);
        var html = [];
        if (section === "sidebar") {
            if (index) html.push("<br>");
        } else {
            if (!index) html.push("<p class='images'>");
        }
        html.push("<a href='" + item.hostPageUrl + "'>");
        var title = escape(item.name) + "\n" + getHost(item.hostPageDisplayUrl);
        html.push("<img src='"+ item.thumbnailUrl + "&h=" + height + "&w=" + width +
            "' height=" + height + " width=" + width + " title='" + title + "' alt='" + title + "'>");
        html.push("</a>");
        return html.join("");
    },
    // Other renderers are omitted from this sample...
}

Der Bildrenderer:

  • Berechnet die Miniaturansichtsgröße des Bilds (breite variiert, während die Höhe bei 60 Pixeln festgelegt ist).
  • Fügt den HTML-Code ein, der dem Bildergebnis basierend auf dem Kontext vorausgeht.
  • Erstellt das HTML-<a>-Tag, das mit der Seite verknüpft ist, die das Bild enthält.
  • Erstellt das HTML-<img>-Tag, um die Miniaturansicht des Bilds anzuzeigen.

Der Bildrenderer verwendet die section und index Variablen, um Die Ergebnisse je nachdem, wo sie angezeigt werden, unterschiedlich anzuzeigen. Ein Zeilenumbruch (<br>-Tag) wird zwischen den Bildergebnissen in der Seitenleiste eingefügt, sodass die Seitenleiste eine Spalte mit Bildern anzeigt. In anderen Abschnitten wird vor dem ersten Bildergebnis (index === 0) ein <p>-Tag eingefügt.

Die Größe der Miniaturansicht wird sowohl im <img>-Tag als auch in den Feldern h und w innerhalb der URL der Miniaturansicht verwendet. Die Attribute title und alt (eine Textbeschreibung des Bilds) werden aus dem Namen des Bilds und dem Hostnamen in der URL erstellt.

Hier ist ein Beispiel dafür, wie Bilder in der Beispiel-App angezeigt werden:

[Bing-Bildergebnisse]

Client-ID speichern

Antworten von den Bing-Such-APIs können einen X-MSEdge-ClientID Header enthalten, der mit jeder aufeinander folgenden Anforderung an die API zurückgesendet werden soll. Wenn mehr als eine der Bing Search-APIs von Ihrer App verwendet wird, stellen Sie sicher, dass die gleiche Client-ID mit jeder Anforderung über Dienste hinweg gesendet wird.

Wenn Sie den X-MSEdge-ClientID Header angeben, können die Bing-APIs die Suchvorgänge eines Benutzers zuordnen. Erstens ermöglicht es der Bing-Suchmaschine, den früheren Kontext auf Suchvorgänge anzuwenden, um Ergebnisse zu finden, die die Anforderung besser erfüllen. Wenn ein Benutzer zuvor nach Begriffen im Zusammenhang mit Segeln gesucht hat, z. B. könnte eine spätere Suche nach "Knoten" bevorzugt Informationen zu Knoten zurückgeben, die beim Segeln verwendet werden. Zweitens kann Bing zufällig benutzer auswählen, um neue Features zu erleben, bevor sie allgemein verfügbar gemacht werden. Wenn Sie die gleiche Client-ID für jede Anforderung bereitstellen, wird sichergestellt, dass Benutzer, die ausgewählt wurden, ein Feature immer sehen. Ohne die Client-ID wird dem Benutzer möglicherweise ein Feature angezeigt und verschwindet scheinbar zufällig in den Suchergebnissen.

Browsersicherheitsrichtlinien wie cross-Origin Resource Sharing (CORS) können verhindern, dass die Beispiel-App auf den X-MSEdge-ClientID-Header zugreift. Diese Einschränkung tritt auf, wenn die Suchantwort einen anderen Ursprung von der Seite hat, die sie angefordert hat. In einer Produktionsumgebung sollten Sie diese Richtlinie adressieren, indem Sie ein serverseitiges Skript hosten, das den API-Aufruf in derselben Domäne wie die Webseite ausführt. Da das Skript denselben Ursprung wie die Webseite hat, ist der X-MSEdge-ClientID Header dann für JavaScript verfügbar.

Hinweis

In einer Produktionswebanwendung sollten Sie die serverseitige Anforderung trotzdem ausführen. Andernfalls muss Ihr Bing Search API-Abonnementschlüssel auf der Webseite enthalten sein, wo er für alle Personen verfügbar ist, die die Quelle anzeigen. Sie werden für alle Nutzungen unter Ihrem API-Abonnementschlüssel in Rechnung gestellt, auch Anfragen von nicht autorisierten Parteien, daher ist es wichtig, Ihren Schlüssel nicht verfügbar zu machen.

Für Entwicklungszwecke können Sie eine Anforderung über einen CORS-Proxy stellen. Die Antwort dieses Proxytyps verfügt über einen Access-Control-Expose-Headers-Header, der Antwortheader filtert und sie für JavaScript verfügbar macht.

Es ist einfach, einen CORS-Proxy zu installieren, damit unsere Beispiel-App auf den Client-ID-Header zugreifen kann. Führen Sie den folgenden Befehl aus:

npm install -g cors-proxy-server

Ändern Sie als Nächstes den Bing Web Search-Endpunkt in script.js in:

http://localhost:9090/https://api.cognitive.microsoft.com/bing/v7.0/search

Starten Sie den CORS-Proxy mit diesem Befehl:

cors-proxy-server

Lassen Sie das Befehlsfenster geöffnet, während Sie die Beispiel-App verwenden. Durch schließen des Fensters wird der Proxy beendet. Im Abschnitt "erweiterbare HTTP-Header" unter den Suchergebnissen sollte der X-MSEdge-ClientID Header sichtbar sein. Stellen Sie sicher, dass sie für jede Anforderung identisch ist.

Nächste Schritte