StepZen is now part of IBM. For the most recent product information and updates go to
https://www.ibm.com/products/stepzen

Getting Started by Transforming REST to GraphQL

Use the StepZen CLI to create a GraphQL API for backends with REST interfaces in minutes

There are two ways to create your GraphQL API with StepZen when you have a REST backend.

  • Use the command-line interface (CLI) command stepzen import curl to specify an existing REST endpoint - StepZen introspects the endpoint and auto-generates a GraphQL schema for you.
  • Write your schema code in a .graphql GraphQL Schema Definition Language (SDL) file. Use the powerful GraphQL directive @rest to connect the REST endpoint, and with just a few lines of code, you have a working schema.) See How to Connect a REST Service for how to write your GraphQL schema using @rest.

This topic shows how to use stepzen import curl on an existing REST API. This command sends a curl request to StepZen and parses the GraphQL types from the JSON response.

Before you begin

Install and set up your StepZen account and the CLI.

We use stepzen import curl in this section - you can get help for the command using stepzen import curl --help.

GET requests

Use the StepZen CLI to create a GraphQL schema for your new GraphQL API. Follow the steps below to perform this process using our example customers API:

  1. Auto-generate your schemas and resolvers using the following StepZen CLI command:
stepzen import curl https://introspection.apis.stepzen.com/customers --query-name "customers" --query-type "Customer" --name "customers"
  1. Run stepzen start to upload and deploy your introspected schema.

Let's take a look at what the stepzen import curl command does:

  1. StepZen issues the curl call (we support most, but not all, curl flags, more below).

  2. It converts the returned JSON into a set of GraphQL types.

    The root of the returned JSON was given a special name, in this CustomerEntry, based on the query-type flag. This flag is optional, but it is good to give a meaningful name for the root because otherwise, StepZen will name it RootEntry.

    Furthermore, if you do two different stepzen import curl, the RootEntry will be a type name clash. Other types get fairly good names based on the name in the JSON structure. If you are worried about type name clashes on them, you can use a --prefix flag (more on it later).

  3. It then generates a query with the value of the --query-name flag so that when you execute the query, it will parse the returned JSON into the correct GraphQL structure.

    While this flag is optional, it is highly recommended because otherwise, the default name would be myQuery, and not only is it not a great name, it will clash with any subsequent stepzen import curl commands that you run.

  4. It stores the generated schema in a directory with the name given in name flag. It is optional, and it will create a directory that starts with curl (for the first one, and curl-01 etc., for each subsequent stepzen import curl command).

  5. It creates an index.graphql in the root of your working directory containing the path to which the schema file is generated.

So one command did all this for you!

curl with headers

StepZen stores all headers in a config.yaml file. So the following command

stepzen import curl https://api.foo.com/bar -H 'Authorization: Bearer 347ack988dkey'

creates a new file config.yaml that has an entry like this:

configurationset:
  - configuration:
      name: some-auto-generated-name
      Authorization: Bearer 347ack988dkey

(there might be other entries in it too).

It also modifies the generated schema to create a query like:

type Query {
  myQuery: RootEntry
    @rest(
      endpoint: "https://api.foo.com/bar"
      configuration: "some-auto-generated-name"
    )
}

This way, your secrets (typically in headers) are stashed away separately from your code (your schema (SDL) file).

Even if you do not have headers but are sending an apikey or something else in the endpoint, you can move it away to config.yaml.

curl with query parameters

StepZen automatically converts all curl query parameters to arguments in the GraphQL query that gets generated. For example, https://api.foo.com/bar?name=anant&country=US generates the following query:

type Query {
  myQuery(name: String!, country: String!): RootEntry
    @rest(endpoint: "https://api.foo.com/bar")
}

Where did the query arguments go? In StepZen, we have a default behavior of appending all GraphQL query arguments to the endpoint URL as query string parameters. So in effect this the same as:

type Query {
  myQuery(name: String!, country: String!): RootEntry
    @rest(endpoint: "https://api.foo.com/bar?name=$name&country=$country")
}

In this form, you get more control. So for example, you can say things like:

type Query {
  myQuery(username: String!, country: String!): RootEntry
    @rest(endpoint: "https://api.foo.com/bar?name=$username&country=$country")
}

When you don't want the GraphQL query arguments automatically appended to the URL

You can specify rules to prevent StepZen from auto-appending the GraphQL query arguments and query string parameters - for example, when the URL already has a query string, or when you want to use the arguments somewhere else than URL query string (e.g. in pathname or headers).

  1. When there is already a query parameter. For example, you might do a

stepzen import curl "https://api.foo.com/bar?name=anant&country=US"

and edit the SDL to be (i.e. only allow for queries on country=US):

  type Query {
    myQuery(name: String!): RootEntry
      @rest(endpoint: "https://api.foo.com/bar?country=US")
}

and you might think that name will get added as a query parameter, but it will not. In this case, your SDL needs to be:

  type Query {
    myQuery(name: String!): RootEntry
      @rest(endpoint: "https://api.foo.com/bar?country=US&name=$name")
}
  1. You want to suppress parameters because they might be used in path or headers.

    In that case, add an extra line to your config.yaml. It sets the attribute stepzen.queryextensionguard to true, which instructs StepZen not to automatically append query parameters to the request by setting. An example of that file follows:

configurationset:
  - configuration:
      name: "config"
      stepzen.queryextensionguard: true

curl with path parameters

StepZen can automatically convert path parameters into arguments.

stepzen import curl https://example.com/users/jane/posts/12 --path-params '/users/$userId/posts/$postId'

generates a query in GraphQL like this:

type Query {
  myQuery(userId: String!, postId: Int!): RootEntry
    @rest(endpoint: "https://example.com/users/$userId/posts/$postId")
}

Customizing the autogenerated schema

The @rest that is generated from stepzen import curl can be customized to add

  • transforms (to modify the response),
  • filter (to filter the output),
  • setters and resultroot to change names of fields etc.

For a full overview of all the configuration options, see Using POST with REST.

POST requests

When using stepzen import curl for a POST request, parameter substitution gets applied to the body of your request.

Making all fields in POST body as query arguments

This is the simplest case:

stepzen import curl 'http://dummy.restapiexample.com/api/v1/create' -d '{"key1":"value1", "key2":"value2"}' -H 'Content-Type: application/json'
  • The default header of a curl request that contains -d (or --data-raw) is Content-Type: application/x-www-form-urlencoded.
  • As GraphQL APIs rely on JSON, you must append the header -H 'Content-Type: application/json' to use JSON in your post body.

The stepzen import curl command above generates a query in GraphQL like this:

type Query {
  myQuery(key1: String, key2: String): RootEntry
    @rest(
      method: POST
      endpoint: "http://dummy.restapiexample.com/api/v1/create"
    )
}
  • The argument method with the value POST has been added to the @rest directive.
  • The JSON keys from the body are transformed into query arguments.

Generating a mutation from a POST request

When using stepzen import curl, the default GraphQL operation type is Query. To change the above import into a Mutation manually update the schema:

type Mutation {
  myQuery(key1: String, key2: String): RootEntry
    @rest(
      method: POST
      endpoint: "http://dummy.restapiexample.com/api/v1/create"
    )
}

Handling more complex parameter substitutions

Today stepzen import curl for POST does not handle more complicated parameter substitutions. For an overview of all the configuration options, see Using POST with REST.

Best practices

Working with multiple curl requrests

You can issue as many curl requests as you want. As a matter of best practice, use:

  • --query-name gives unique names to the queries to avoid query name clashes.

  • --query-type gives the Root unique names to avoid root name clashes.

  • --prefix to prefix all non-root types. So for example, --prefix Cust makes all types have a Cust prefix, and this avoids type conflicts.

  • --name to keep the directories for each imported curl different.

Undoing something

You will likely make some mistakes. To undo something that did not work as you intended (you gave the wrong path variables, you forgot to give a prefix or a query name, or whatever), you should:

  1. Delete the generated directory because of stepzen import curl. It would have the name you gave in --name flag, or curl or curl-xx.
  2. Edit the index.graphql in the root of your working directory, and remove the entry for that file (e.g., curl/index.graphql).

That's it. Then try your stepzen import curl again.

Learn More

Congratulations! You've created a GraphQL API based on a REST API that includes queries, parameters, and mutations.

To extend your schema or start from scratch to write your schema code yourself, you can use the GraphQL declarative construct @rest. See How to Connect a REST Service.