Can't embed image url from APi

3.7k Views Asked by At

I've been following along a coding tutorial that pulls recipe info from an API and displays it on a page.

Everything was working fine until I stepped away for a bit and came back. Now the image URL from the fetch request won't properly display when I insert the markup onto the page.

In the console it shows that the entire API fetch request went through and the data is there, but the image won't embed.

I'm getting this error:

Failed to load resource: net::ERR_BLOCKED_BY_RESPONSE.NotSameOriginAfterDefaultedToSameOriginByCoep

enter image description here

Here is my fetch request and embed code that I'm using:

Fetch code:

export const state = {
  recipe: {},
};

export const loadRecipe = async function (id) {
  try {
    const response = await fetch(
      `https://forkify-api.herokuapp.com/api/v2/recipes/${id}`
      // `https://forkify-api.herokuapp.com/api/v2/recipes/5ed6604591c37cdc054bce57`
    );
    console.log(response);
    const data = await response.json();
    console.log(response, data);

    if (!response.ok) throw new Error(`${data.message} (${response.status})`);

    const { recipe } = data.data;

    console.log(recipe);

    state.recipe = {
      id: recipe.id,
      title: recipe.title,
      publisher: recipe.publisher,
      sourceUrl: recipe.source_url,
      servings: recipe.servings,
      image: recipe.image_url,
      cookingTime: recipe.cooking_time,
      ingredients: recipe.ingredients,
    };
    console.log(`--- this is the recipe object ---`);
    console.log(state.recipe);
  } catch (error) {
    alert(error);
  }
};

Embed Code module:

class RecipeView {
  #parentElement = document.querySelector('.recipe');
  #data;

  render(data) {
    this.#data = data;
    const markup = this.#generateMarkup();
    this.#clear();
    console.log(`=== image link ===`);
    console.log(this.#data.image);
    this.#parentElement.insertAdjacentHTML('afterbegin', markup);
  }
  renderSpinner() {
    const spinnerMarkup = `
      <div class="spinner">
        <svg>
          <use href="${icons}#icon-loader"></use>
        </svg>
      </div>`;
    this.#clear();
    this.#parentElement.insertAdjacentHTML('afterbegin', spinnerMarkup);
  }
  #clear() {
    this.#parentElement.innerHTML = '';
  }
  #generateMarkup() {
    return `
        <figure class="recipe__fig">
        <img src="${this.#data.image}" alt="${
      this.#data.title
    }" class="recipe__img" />
        <h1 class="recipe__title">
            <span>${this.#data.title}</span>
        </h1>
        </figure>

        <div class="recipe__details">
        <div class="recipe__info">
            <svg class="recipe__info-icon">
            <use href="${icons}#icon-clock"></use>
            </svg>
            <span class="recipe__info-data recipe__info-data--minutes">${
              this.#data.cookingTime
            }</span>
            <span class="recipe__info-text">minutes</span>
        </div>
        <div class="recipe__info">
            <svg class="recipe__info-icon">
            <use href="${icons}#icon-users"></use>
            </svg>
            <span class="recipe__info-data recipe__info-data--people">4</span>
            <span class="recipe__info-text">servings</span>

            <div class="recipe__info-buttons">
            <button class="btn--tiny btn--increase-servings">
                <svg>
                <use href="${icons}#icon-minus-circle"></use>
                </svg>
            </button>
            <button class="btn--tiny btn--increase-servings">
                <svg>
                <use href="${icons}#icon-plus-circle"></use>
                </svg>
            </button>
            </div>
        </div>

        <div class="recipe__user-generated">
            <svg>
            <use href="${icons}#icon-user"></use>
            </svg>
        </div>
        <button class="btn--round">
            <svg class="">
            <use href="${icons}#icon-bookmark-fill"></use>
            </svg>
        </button>
        </div>

        <div class="recipe__ingredients">
        <h2 class="heading--2">Recipe ingredients</h2>
        <ul class="recipe__ingredient-list">
            ${this.#data.ingredients
              .map(ing => {
                return `
            <li class="recipe__ingredient">
            <svg class="recipe__icon">
                <use href="${icons}#icon-check"></use>
            </svg>
            <div class="recipe__quantity">${ing.quantity || ''}</div>
            <div class="recipe__description">
                <span class="recipe__unit">${ing.unit}</span>
                ${ing.description}
            </div>
            </li>`;
              })
              .join('')}


            <li class="recipe__ingredient">
            <svg class="recipe__icon">
                <use href="${icons}#icon-check"></use>
            </svg>
            <div class="recipe__quantity">0.5</div>
            <div class="recipe__description">
                <span class="recipe__unit">cup</span>
                ricotta cheese
            </div>
            </li>
        </ul>
        </div>

        <div class="recipe__directions">
        <h2 class="heading--2">How to cook it</h2>
        <p class="recipe__directions-text">
            This recipe was carefully designed and tested by
            <span class="recipe__publisher">${
              this.#data.publisher
            }</span>. Please check out
            directions at their website.
        </p>
        <a
            class="btn--small recipe__btn"
            href="${this.#data.sourceUrl}"
            target="_blank"
        >
            <span>Directions</span>
            <svg class="search__icon">
            <use href="${icons}#icon-arrow-right"></use>
            </svg>
        </a>
        </div>`;
  }
}

I appreciate any help on this as I've been ripping my hair out trying to resolve this issue.

3

There are 3 best solutions below

0
On

You might have a misconfigured response header. Security response headers are HTTP headers that web servers/applications can set when returning data to web clients. They are used to communicate security policy settings for a web browser that is interacting with the web site. You might find some answers here https://developer.chrome.com/docs/devtools/network/reference/#headers

1
On

I was able to resolve this issue (as a workaround so that I could continue on with the course) by updating my loadSearchResults function so that the returned object references 'rec.image' instead of "rec.img_url"

export const loadSearchResults = async function(query) {
  try {
    state.search.query = query;
    const data = await getJSON(`${API_URL}?search=${query}`);
    console.log(data);

    state.search.results = data.data.recipes.map(rec => {
      return {
        id: rec.id,
        title: rec.title,
        publisher: rec.publisher,
        image: rec.image,
      };
    });
  } catch (err) {
    console.error(`${err}`);
    throw err;
  }
};

enter image description here

1
On

I'm doing the same tutorial right now. I was just able to fix it by adding in the html image tag crossorigin="anonymous" . See if that will fix it for you.