Shopify Function: Request not reaching the remote server from Shopify using the network access api

Shopify Function: Request not reaching the remote server from Shopify using the network access api

learntobuild
Shopify Partner
1 0 0

Hello,

 

I am trying to build a Shopify function extension in Rust.

I wished to make an API request from inside my function. To do that, Shopify provides it's own way of handling requests.

 

I am following this article: https://shopify.dev/docs/apps/functions/input-output/network-access/using-network-access

 

src/fetch.rs

use shopify_function::prelude::*;
use shopify_function::Result;

#[shopify_function_target(query_path = "src/fetch.graphql", schema_path = "schema.graphql")]
fn fetch(input: fetch::input::ResponseData) -> Result<fetch::output::FunctionFetchResult> {
    let mut request: Option<output::HttpRequest> = None;

    // Network call if the buyer_identity is present
    if let Some(buyer_identity) = &input.cart.buyer_identity {
        // Network call if the email is present
        if let Some(_email) = &buyer_identity.email {
            let http_request = build_request(&input);
            request = Some(http_request);
        }
    }

    Ok(fetch::output::FunctionFetchResult { request })
}

fn build_request(input: &fetch::input::ResponseData) -> fetch::output::HttpRequest {
    // Serializing the input for simple demonstration, the body can be articulated as needed.
    let body = serde_json::to_string(&input).expect("Error serializing");

    static SERVER_URL: &'static str = "https://subdomain.example.com/some-endpoint";

    fetch::output::HttpRequest {
        method: fetch::output::HttpRequestMethod::Other("POST".to_string()),
        url: SERVER_URL.to_string(),
        headers: [].to_vec(),
        body: Some(body),
        policy: fetch::output::HttpRequestPolicy {
            read_timeout_ms: 20000,
        },
    }
}

src/fetch.graphql

query Input {
  cart {
    buyerIdentity {
      email
      isAuthenticated
    }
    cost {
      totalAmount {
        amount
        currencyCode
      }
    }
  }
}

 

 

src/run.rs

use shopify_function::prelude::*;
use shopify_function::Result;

use serde::Deserialize;

#[derive(Deserialize)]
struct ServerResponse {
    errors: Vec<ServerResponseError>,
}

#[derive(Deserialize)]
struct ServerResponseError {
    localized_message: String,
    target: String,
}

#[shopify_function_target(query_path = "src/run.graphql", schema_path = "schema.graphql")]
fn run(input: run::input::ResponseData) -> Result<run::output::FunctionRunResult> {
    // Optimization for when there are no requests.
    // In this simple example, there are no fallbacks, but there is room to implement one if needed.
    // See fetch.rs.
    if input.fetch_result.is_none() {
        return Ok(output::FunctionRunResult { errors: vec![] });
    }

    let fetch_result = input.fetch_result.unwrap();

    // When the server returns an unexpected response.
    // Optionally: Apply a local fallback error message.
    if fetch_result.status != 200 {
        panic!("Server response unprocessable (status)");
    }

    let body = fetch_result.body.as_ref().expect("Missing response body");
    match serde_json::from_str::<ServerResponse>(body.as_str()) {
        Ok(response) => {
            let errors: Vec<run::output::FunctionError> = response
                .errors
                .into_iter()
                .map(|error| run::output::FunctionError {
                    localized_message: error.localized_message,
                    target: error.target,
                })
                .rev()
                .collect();

            return Ok(run::output::FunctionRunResult { errors });
        }
        Err(_) => {
            // Optionally: Apply a local fallback error message.
            panic!("Server response unprocessable (serialization)");
        }
    }
}

src/run.graphql

query Input {
  fetchResult {
    status
    headers {
      name
      value
    }
    body
  }
}

 

 

I built and deployed this app to Shopify.

Then, I activated it from the test app's checkout settings.

 

I tested it by building a sample cart and going to checkout.

But, each time it gives the same thing in the logs:

learntobuild_0-1711354689438.png

 

 

To further narrow down the issue, I checked the logs on my API server. The server isn't receiving the HTTP request.

I am confused as to what is happening here.

All help would be appreciated.

Thank you.

Replies 5 (5)

Nick_Wesselman
Shopify Staff
170 43 69

This is an early access feature with limited availability, have you confirmed that it's been enabled for the shop in question?

Nick Wesselman | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

GeorgeHoffman
Shopify Partner
27 0 4

Is it early access for every type of function ... why doesn't the first row say early access but the next 2 do. It would have saved me the entire day tracking it down. Shopify likes to give me a taste of hope then crush my dreams. When is this critical (I would almost say obvious basic necessary) feature going to be available for real big-boy enterprise apps. IT WOULD BE REALLY NICE TO HAVE BEFORE AUGUST WHEN YOU FORCE US TO REWRITE OUR CHECKOUT LIQUID PAGES........

 

GeorgeHoffman_0-1716413267734.png

 

GeorgeHoffman
Shopify Partner
27 0 4

and now Ive tried it on a developer preview store with same result. i feel like Im following the Shopify example here pretty closely.

 

GeorgeHoffman_0-1716416330436.png

 

Nick_Wesselman
Shopify Staff
170 43 69

Sorry, my answer was not complete -- in the case of cart validation, this is only available on the Shopify for enterprise plan. It is not enabled in any developer preview on Partners without a production shop on this plan.

Nick Wesselman | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

GeorgeHoffman
Shopify Partner
27 0 4
That was my confusion it was the first I heard of an enterprise plan. I thought it was maybe a typo in the documentation since I thought my org had the highest level plan available (plus). Looking on the pricing page I do indeed see a mysterious enterprise option tucked away at the bottom with just a request info button and a contact form. I filled it out but I am yet to have anyone contact me with info. It's unfortunate if we have to upgrade our plan just to get some basic feature like secure server to server calls at checkout.