Eduardo
Eduardo

Reputation: 7141

Adding A Header when using Swagger UI

The endpoint where my swagger.json file (localhost:8000/rest/swagger.json) requires an AuthType header to access it. How can I get Swagger UI to add this when it makes its initial request for the swagger.json file?


What I've tried so far:

$(function () {
    var token = 'xxx';
    window.swaggerUi = new SwaggerUi({
        url: "http://" + location.host + "/rest/swagger.json",
        dom_id: "swagger-ui-container",
        supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
        onComplete: function (swaggerApi, swaggerUi) {
            var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("AuthToken", token, "header");
            window.swaggerUi.api.clientAuthorizations.add("AuthToken", apiKeyAuth);
            $('pre code').each(function (i, e) {
                hljs.highlightBlock(e)
            });
        },
        docExpansion: "none",
        apisSorter: "alpha",
        showRequestHeaders: false
    });

    swaggerUi.load();
});

But when I open Chrome Dev Tools and look at what request was made to localhost:8000/rest/swagger.json it has no AuthType header and has a 401 Unauthorized response.

Note: It doesn't seem like the onComplete function ever gets called (i'm guessing it requests swagger.json before that would usually get called so it falls into the onFailure block instead when the request fails)

Upvotes: 2

Views: 7913

Answers (2)

dakshgautam
dakshgautam

Reputation: 39

I will provide you my scenario. To be very honest the READ-ME of swagger is not upto the mark(that is my view) . They have not mentioned anything about adding a header to the url request.

My use case was that i had to call my API to get JSON response.(My API was protected by login_required decorator , which requires xcsrf-token to be sent in the header )

In your case, yours localhost:8000/rest/swagger.json is analogous to my API.

How to approach this problem?

  1. When we SwaggerUIBundle.A key named "spec" ( will explain spec later in the snippet) has to be mapped with JSON response value . This JSON response provides initial structure for swagger-ui page .

What are you saying ? What kind of UI are you talking about ? What is the structure of JSON Response ?

Click here for Swagger-UI example

To make page of this type using swagger-ui you need to supply it with JSON reponse

Click here for JSON reponse that you need to generate either using APIs or in your case ocalhost:8000/rest/swagger.json

  1. Use AJAX request to make a call to your API or localhost:8000/rest/swagger.json.

  2. Now in your success call, JSON has to be equated to "spec".

Explanation Using Code Snippets

  1. Instantiate SwaggerUIBundle object. Notice spec key which has to be mapped to JSON response value. dom_id can be ID of any div.

  const ui = SwaggerUIBundle({
    spec: {},// put JSON response here.
    dom_id: '#swagger-ui',
    presets: [
      SwaggerUIBundle.presets.apis,
      // yay ES6 modules ↘
      Array.isArray(SwaggerUIStandalonePreset) ? SwaggerUIStandalonePreset : SwaggerUIStandalonePreset.default
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl
    ],
    layout: "StandaloneLayout"
  })
  window.ui = ui

  1. Now enclose this object instantiation, in a function .

window.foo = function(spec){
  const ui = SwaggerUIBundle({
    spec: spec,
    dom_id: '#swagger-ui',
    presets: [
      SwaggerUIBundle.presets.apis,
      // yay ES6 modules ↘
      Array.isArray(SwaggerUIStandalonePreset) ? SwaggerUIStandalonePreset : SwaggerUIStandalonePreset.default
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl
    ],
    layout: "StandaloneLayout"
  })
  window.ui = ui
}

  1. Let us see how we can use ajax calls to call this function. We can add any token during this AJAX call.

window.onload = function() {
   function apiCall(uri, data, methodType) {
  const csrftoken = getCookie('csrftoken');
  //Add header to the URL . 
  $.ajaxSetup({
    beforeSend: function(xhr, settings) {
      if (!this.crossDomain) {
          xhr.setRequestHeader('X-CSRFToken', csrftoken);
      }
    }
  });
  
  $.ajax({
    url: uri,
    method: methodType,
    contentType: 'application/json',
    data: data,
    success: function (response) {
      var script = document.createElement('script');
      // Calling the function which instantiates swaggerbundle object
      foo(response)
    },
    error: function (error) {
    }
  });
}


// You can write your own getCookie function . 
function getCookie(name) {
  let cookieValue = null;
  if (document.cookie && document.cookie !== '') {
    let cookies = document.cookie.split(';');
    for (let i = 0; i < cookies.length; i++) {
      let cookie = jQuery.trim(cookies[i]);
      // Does this cookie string begin with the name we want?
      if (cookie.substring(0, name.length + 1) === (name + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }
  return cookieValue;
}
  
  //['GET','POST'] 
  apiCall('http://localhost:8000/rest/swagger.json',{},'GET');
  
}

  1. Here is the final snippet .

window.foo = function(spec){
  const ui = SwaggerUIBundle({
    spec: spec,
    dom_id: '#swagger-ui',
    presets: [
      SwaggerUIBundle.presets.apis,
      // yay ES6 modules ↘
      Array.isArray(SwaggerUIStandalonePreset) ? SwaggerUIStandalonePreset : SwaggerUIStandalonePreset.default
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl
    ],
    layout: "StandaloneLayout"
  })
  window.ui = ui
}

window.onload = function() {
   function apiCall(uri, data, methodType) {
  const csrftoken = getCookie('csrftoken');
  //Add header to the URL . 
  $.ajaxSetup({
    beforeSend: function(xhr, settings) {
      if (!this.crossDomain) {
          xhr.setRequestHeader('X-CSRFToken', csrftoken);
      }
    }
  });
  
  $.ajax({
    url: uri,
    method: methodType,
    contentType: 'application/json',
    data: data,
    success: function (response) {
      var script = document.createElement('script');
      // Calling the function which instantiates swaggerbundle object
      foo(response)
    },
    error: function (error) {
    }
  });
}


// You can write your own getCookie function . 
function getCookie(name) {
  let cookieValue = null;
  if (document.cookie && document.cookie !== '') {
    let cookies = document.cookie.split(';');
    for (let i = 0; i < cookies.length; i++) {
      let cookie = jQuery.trim(cookies[i]);
      // Does this cookie string begin with the name we want?
      if (cookie.substring(0, name.length + 1) === (name + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }
  return cookieValue;
}
  
  //['GET','POST'] 
  apiCall('http://localhost:8000/rest/swagger.json',{},'GET');
  
}

Upvotes: 3

Betsalel Williamson
Betsalel Williamson

Reputation: 131

In your example you have window.swaggerUi, but have not yet assigned the swaggerApi variable to the window object.

Try:

onComplete: function (swaggerApi, swaggerUi) {

    window.swaggerApi = swaggerApi;

    var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("AuthToken", token, "header");
    window.swaggerUi.api.clientAuthorizations.add("AuthToken", apiKeyAuth);
    $('pre code').each(function (i, e) {
        hljs.highlightBlock(e)
    });
}

Second:

While the browser may be able to figure the correct swaggerUi variable try for the load:

window.swaggerUi.load();

Instead of:

swaggerUi.load();

Upvotes: 2

Related Questions