Expand my Community achievements bar.

SOLVED

error: The API host is not valid: An API host must be provided.

Avatar

Level 1

Hello, 

I'm trying to set up my environment by following the instructions in this link https://github.com/AdobeDocs/adobeio-runtime/blob/stage/quickstarts/setup.md   .

In order to test wsk CLI, I I executed the command "wsk list" but it shows the error "The API host is not valid: An API host must be provided."

Could you please tell me how to fix this error?

Thank you.

 

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Employee

Hi @In_Na - are you trying to set up your Project Firefly environment?

The correct docs would be https://github.com/AdobeDocs/project-firefly/blob/master/getting_started/setup.md.

Please let us know if you have further questions.

View solution in original post

12 Replies

Avatar

Correct answer by
Employee

Hi @In_Na - are you trying to set up your Project Firefly environment?

The correct docs would be https://github.com/AdobeDocs/project-firefly/blob/master/getting_started/setup.md.

Please let us know if you have further questions.

Avatar

Level 1

Hello @duypnguyen
Yes, I'm trying to set up my Project Firefly environment. Thank you for the docs.

I'm now trying to invoke the action "generic" (6.2 Trying the Sample Application). I put the token into this following format {"Authorization":"Bearer eyJ4NXxxxxxxxxxxxxx"} and I put it in the "header" but I get the error "cannot authorize request, reason: missing authorization header". Is it the right format ? Can you help me fix this error please ? 

Thank you.

Avatar

Employee
@In_Na - it's hard to say without seeing your setup visually. Could you please share the curl command? How did you receive the token? In addition, you might find this doc useful: https://github.com/AdobeDocs/project-firefly/blob/master/getting_started/common_troubleshooting.md.

Avatar

Level 1

Hello @duypnguyen,

Thank you for your answer.

Actually, I don't know where to find the curl command. I'm a beginner using this tool.

I have solved the error "The API host is not valid: An API host must be provided". It was about setting up the .wskprops file. 
But, I still can't invoke the action "generic". I get the error "cannot authorize request, reason: missing x-gw-ims-org-id header". 

Avatar

Employee

Hi @In_Na - that's expected, you also need to add the header x-gw-ims-org-id to the request with the value of your org ID (for example ABC123@AdobeOrg).

Also, are you following the "getting started with Project Firefly": https://www.adobe.io/apis/experienceplatform/project-firefly/docs.html#!AdobeDocs/project-firefly/ma... ? If not, I would strongly recommend to do so. Please ignore all wsk commands as well as .wskprops. You should only need aio commands for your app.

Avatar

Level 1

Hello @duypnguyen, I'm trying to follow this tutorial "Lesson 4: List All Customer Profiles on the UI" : https://adobeio-codelabs-campaign-standard-adobedocs.project-helix.page/?src=/lessons/lesson4.html but it doesn't work. I'm wondering if there is another link for the same tutorial which is up to date please ? Thank you

Avatar

Employee
@In_Na - glad to hear you are following the code lab. It is actively maintained with up-to-date content. Which error are you getting exactly?

Avatar

Level 1

@duypnguyen Actually I got the error " Cannot read property 'state' of andefined" at the app.js at this line "const profiles = this.state.profiles".

Here is my ActionForm.js 

 

 

/* 
* <license header>
*/

import React, { useState } from 'react'
import PropTypes from 'prop-types'
import ErrorBoundary from 'react-error-boundary'
import {
  Flex,
  Heading,
  Form,
  Picker,
  TextArea,
  Button,
  ActionButton,
  StatusLight,
  ProgressCircle,
  Item,
  Text,
  View
} from '@adobe/react-spectrum'
import Function from '@spectrum-icons/workflow/Function'

import actions from '../config.json'
import actionWebInvoke from '../utils'

const ActionsForm = (props) => {
  const [state, setState] = useState({
    actionSelected: null,
    actionResponse: null,
    actionResponseError: null,
    actionHeaders: null,
    actionHeadersValid: null,
    actionParams: null,
    actionParamsValid: null,
    actionInvokeInProgress: false,
    actionResult: '',
    profiles: null
  })

  return (
    <View width="size-6000">
      <Heading level={1}>Run your application backend actions</Heading>
      {Object.keys(actions).length > 0 && (
        <Form necessityIndicator="label">
          <Picker
            label="Actions"
            isRequired={true}
            placeholder="select an action"
            aria-label="select an action"
            items={Object.keys(actions).map((k) => ({ name: k }))}
            itemKey="name"
            onSelectionChange={(name) =>
              setState({
                ...state,
                actionSelected: name,
                actionResponseError: null,
                actionResponse: null
              })
            }
          >
            {(item) => <Item key={item.name}>{item.name}</Item>}
          </Picker>

          <TextArea
            label="headers"
            placeholder='{ "key": "value" }'
            validationState={state.actionHeadersValid}
            onChange={(input) =>
              setJSONInput(input, 'actionHeaders', 'actionHeadersValid')
            }
          />

          <TextArea
            label="params"
            placeholder='{ "key": "value" }'
            validationState={state.actionParamsValid}
            onChange={(input) =>
              setJSONInput(input, 'actionParams', 'actionParamsValid')
            }
          />
          <Flex>
            

            <ProgressCircle
              aria-label="loading"
              isIndeterminate
              isHidden={!state.actionInvokeInProgress}
              marginStart="size-100"
            />
          </Flex>
        </Form>
      )}

      {state.actionResponseError && (
        <View padding={`size-100`} marginTop={`size-100`} marginBottom={`size-100`} borderRadius={`small `}>
          <StatusLight variant="negative">Failure! See the complete error in your browser console.</StatusLight>
        </View>
      )}
      {!state.actionResponseError && state.actionResponse && (
        <View padding={`size-100`} marginTop={`size-100`} marginBottom={`size-100`} borderRadius={`small `}>
          <StatusLight variant="positive">Success! See the complete response in your browser console.</StatusLight>
        </View>
      )}

      {Object.keys(actions).length === 0 && <Text>You have no actions !</Text>}
        <TextArea
            label="results"
            isReadOnly={true}
            width="size-6000"
            height="size-6000"
            maxWidth="100%"
            value={state.actionResult}
            validationState={( !state.actionResponseError ) ? 'valid' : 'invalid'}
          />
    </View>
  )

  // Methods
  async function componentWillMount () {
    this.setState({ actionInvokeInProgress: true })
    
    const headers = {}
    const params = {}
  
    // set the authorization header and org from the ims props object
    if (this.props.ims.token && !headers.authorization) {
      headers.authorization = 'Bearer ' + this.props.ims.token
    }
    if (this.props.ims.org && !headers['x-gw-ims-org-id']) {
      headers['x-gw-ims-org-id'] = this.props.ims.org
    }
    try {
      const actionResponse = await actionWebInvoke('get-profiles', headers, params)
      this.setState({ profiles: actionResponse.body.content, actionResponseError: null, actionInvokeInProgress: false })
      console.log(`action response:`, actionResponse)
    } catch (e) {
      console.error(e)
      this.setState({ profiles: null, actionResponseError: e.message, actionInvokeInProgress: false })
    }
  }
 
}

ActionsForm.propTypes = {
  runtime: PropTypes.any,
  ims: PropTypes.any
}

export default ActionsForm

 

 

And here is my App.js

 

 

/* 
* <license header>
*/

import React from 'react'
import { Provider, defaultTheme, Grid, View, Flex } from '@adobe/react-spectrum'
import ErrorBoundary from 'react-error-boundary'
import { HashRouter as Router, Switch, Route } from 'react-router-dom'
import SideBar from './SideBar'
import ActionsForm from './ActionsForm'
import { Home } from './Home'
import { About } from './About'

function App (props) {
  console.log('runtime object:', props.runtime)
  console.log('ims object:', props.ims)

  // use exc runtime event handlers
  // respond to configuration change events (e.g. user switches org)
  props.runtime.on('configuration', ({ imsOrg, imsToken, locale }) => {
    console.log('configuration change', { imsOrg, imsToken, locale })
  })
  // respond to history change events
  props.runtime.on('history', ({ type, path }) => {
    console.log('history change', { type, path })
  })

  const profiles = this.state.profiles
  console.log(`profiles object:`, profiles)

  return (
    <ErrorBoundary onError={onError} FallbackComponent={fallbackComponent}>
      <Router>
      <Provider UNSAFE_className='provider' theme={ defaultTheme }>
      <Flex UNSAFE_className='main'>
        <Heading UNSAFE_className='main-title'>Welcome to customers-dashboard!</Heading>

        <Flex UNSAFE_className='profiles'>
          <h3 className='main-title'>Customer Profiles</h3>
          <ProgressCircle
                UNSAFE_className='actions-invoke-progress'
                aria-label='loading'
                isIndeterminate
                isHidden={ !this.state.actionInvokeInProgress }/>
          { !!profiles &&
            <Grid>
              {profiles.map((profile, i) => {
                return <Flex UNSAFE_className='profile'>Name: { profile['firstName'] } { profile['lastName'] } - Email: { profile['email'] } - Date of birth: { profile['birthDate'] }</Flex>
              })}

            </Grid>
          }
          { !profiles &&
            <Text>No profiles!</Text>
          }

        </Flex>
      </Flex>
    </Provider>
      </Router>
    </ErrorBoundary>
  )

  // Methods

  // error handler on UI rendering failure
  function onError (e, componentStack) { }

  // component to show if UI fails rendering
  function fallbackComponent ({ componentStack, error }) {
    return (
      <React.Fragment>
        <h1 style={{ textAlign: 'center', marginTop: '20px' }}>
          Something went wrong :(
        </h1>
        <pre>{componentStack + '\n' + error.message}</pre>
      </React.Fragment>
    )
  }
}

export default App

 

 

Avatar

Level 1

@duypnguyenActually I got the error " Cannot read property 'state' of undefined" at the App.js at the line "const profiles = this.state.profiles"

 

 

 

 

Avatar

Employee
Problem has been solved via DM. We will make some improvements for the codelab so that it's up to date with the generated UI from app template.