# Single HTTP Quickstart

> **Info:** Follow [composite quickstart](https://tray.ai/documentation/developer/connector-development-kit/overview/quickstarts/composite) if you are building up a Helper / Utility connector.

This is a follow up guide after Raw HTTP quickstarts. We will show you how to build a HTTP operation on a service connector.

## Objective

Build a HTTP operation 'get\_top\_rated\_movies' using  endpoint.

## Pre-requisite

***

Follow the [Raw HTTP (token) quickstart](https://tray.ai/documentation/developer/connector-development-kit/overview/quickstarts/token-raw-http) to complete the auth setup and deploy the TMDB connector with a Raw HTTP operation.

## 1. Add new operation

***

Add a new operation using:

`tray-cdk connector add-operation get_top_rated_movies http`

where `get_top_rated_movies` is the operation name and `http` is operation type.

This would add a new folder under `src` with the following files:

![operation-folder](https://tray.ai/documentation/images/developer/connector-development-kit/developing-connectors/operations/handler-ts-configuration/cdk-operation-folder.png)

Now we are ready to modify these files to build our operation.

## 2. Configure operation files

### input.ts

***

This file will define the schema of the input that is needed for the operation

i.e. it will contain type definitions for any query, URI parameters or request body.

The input object should be blank as our endpoint does not require any inputs.

Here's the complete input.ts for your reference:

```js
export type GetTopRatedMoviesInput = {};
```

### output.ts

***

This file will define the structure of the output that the operation returns.

For building the output schema we can use the JSON output from the API `Try it` step.

```json
{
  "page": 1,
  "results": [
    \{
      "adult": false,
      "backdrop_path": "/tmU7GeKVybMWFButWEGl2M4GeiP.jpg",
      "genre_ids": [
        18,
        80
      ],
      "id": 238,
      "original_language": "en",
      "original_title": "The Godfather",
      "overview": "Spanning the years 1945 to 1955, a chronicle of the fictional Italian-American Corleone crime family. When organized crime family patriarch, Vito Corleone barely survives an attempt on his life, his youngest son, Michael steps in to take care of the would-be killers, launching a campaign of bloody revenge.",
      "popularity": 95.013,
      "poster_path": "/3bhkrj58Vtu7enYsRolD1fZdja1.jpg",
      "release_date": "1972-03-14",
      "title": "The Godfather",
      "video": false,
      "vote_average": 8.7,
      "vote_count": 18651
    \},
    ...
    ...More movie records
    ...
  ],
  "total_pages": 576,
  "total_results": 11514
}
```

If you are familiar with Typescript, the above JSON would translate to the following types in `Output.ts` file:

```js
//movie object
export type GetTopRatedMoviesObject = \{
  adult: boolean,
  backdrop_path: string,
  genre_ids: number[],
  id: number,
  original_language: string,
  original_title: string,
  overview: string,
  popularity: number,
  poster_path: string,
  release_date: string,
  title: string,
  video: boolean,
  vote_average: number,
  vote_count: number,
\};

export type GetTopRatedMoviesOutput = \{
  page: number,
  results: GetTopRatedMoviesObject[], //array of movie objects
  total_pages: number,
  total_results: number,
\};
```

You can copy paste the above snippet into your `Output.ts`.

### handler.ts

***

This file will contain your main function that defines the operation.

Perform the following steps on this file:

1. Replace the URL inside `http.get()` function with `/3/movie/top_rated`. This is cause we already defined the baseUrl in the [global config file](https://tray.ai/documentation/developer/connector-development-kit/overview/quickstarts/token-raw-http#global-config).

2. Remove the line `.addPathParameter('id', input.id.toString())` from the `handleRequest` function chain as our request doesn't need a URI parameter.

3. The endpoint needs the `bearer &lt;token>` to be passed as an `Authorization` header to the operation.

Since we are using a globalConfig, We don't have to pass the auth for the request separately

Here's the complete `handler.ts` code for your reference:

```typescript
import { OperationHandlerSetup } from "@trayio/cdk-dsl/connector/operation/OperationHandlerSetup";
import { TmdbAuth } from "../TmdbAuth";
import { GetTopRatedMoviesInput } from "./input";
import { GetTopRatedMoviesOutput } from "./output";
import { globalConfigHttp } from "../GlobalConfig";

export const getTopRatedMoviesHandler = OperationHandlerSetup.configureHandler<
  TmdbAuth,
  GetTopRatedMoviesInput,
  GetTopRatedMoviesOutput
>((handler) =>
  handler.withGlobalConfiguration(globalConfigHttp).usingHttp((http) =>
    http
      .get("/3/movie/top_rated")
      .handleRequest((_ctx, _input, request) => request.withoutBody())
      .handleResponse((_ctx, _input, response) => response.parseWithBodyAsJson())
  )
);
```

### handler.test.ts

***

This file will have functions that will be used to test your operation defined in `handler.ts`.

A simple test for this endpoint could be to check the total number of movies returned in the response.

As per the documentaion, the endpoint should return 20 movie objects by default.

We can test this with:

`expect(outputValue.results.length).toEqual(20);`

Here's the complete `handler.test.ts` code for your reference:

```js
import { OperationHandlerTestSetup } from "@trayio/cdk-dsl/connector/operation/OperationHandlerTest";
import { OperationHandlerResult } from "@trayio/cdk-dsl/connector/operation/OperationHandler";
import { getTopRatedMoviesHandler } from "./handler";
import "@trayio/cdk-runtime/connector/operation/OperationHandlerTestRunner";

OperationHandlerTestSetup.configureHandlerTest(
  getTopRatedMoviesHandler,
  (handlerTest) =>
    handlerTest
      .usingHandlerContext("test")
      .nothingBeforeAll()
      .testCase("should return 20 movies", (testCase) =>
        testCase
          .givenNothing()
          .when(() => ({}))
          .then(({ output }) => \{
            // console.log(output);
            const outputValue = OperationHandlerResult.getSuccessfulValueOrFail(output);
            expect(outputValue.results.length).toEqual(20);
          \})
          .finallyDoNothing()
      )
      .nothingAfterAll()
);
```

## 3. Test the operation

***

You can test the operation now by:

`tray-cdk connector test [OPERATION_NAME]`

in our case this is, `tray-cdk connector test get_top_rated_movies`

```cli
> acme-tmdb@1.0.0 test
> jest --config ./jest.config.js "get_top_rated_movies"

 PASS  src/get_top_rated_movies/handler.test.ts
  Operation get_top_rated_movies Test
    ✓ should return 20 results (83 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.154 s, estimated 2 s
Ran all test suites matching /get_top_rated_movies/i.
```

> **You can also do \`npm test\` which will test all operations in the connector's directory.**&#x20;

In case your test results fail, you can visualize the actual API request that was made and the response that was received by logging either or both of them.

Here's how the handler function in `handler.ts` looks with logging enabled for both request and response:

```js
export const getTopRatedMoviesHandler =
  OperationHandlerSetup.configureHandler<AcmeTmdbAuth, GetTopRatedMoviesInput, GetTopRatedMoviesOutput>((handler) =>
    handler.withGlobalConfiguration(globalConfigHttp).usingHttp((http) =>
      http.get("/3/movie/top_rated")
        .handleRequest((ctx, input, request) => {
          console.log(request.withoutBody()) //log the API request to console before sending
          return request.withoutBody()
        })
        .handleResponse((ctx, input, response) => {
          console.log(response) //log the API response to console
          return response.withBodyAsJson()
        })
    )
  );
```

## 4. Deploy the connector

***

The connector is ready to be deployed. Follow the steps as shown on the [Deployment API guide](https://tray.ai/documentation/developer/connector-development-kit/deploying-connectors/deploy-using-api).

## 5. Test on Tray UI

***

Add the connector to a existing / new workflow.

## Next Steps

You can build connectors using CDK now.

Refer to the [auth](https://tray.ai/documentation/developer/connector-development-kit/developing-connectors/authentications/auth-ts) and [input](https://tray.ai/documentation/developer/connector-development-kit/developing-connectors/operations/input-ts-configuration) pages for a full reference on different auth types and input panel configurations.
