# Conexões de Rede

Sua cena pode aproveitar serviços externos que expõem APIs; você pode usar isso para obter dados de preços atualizados, dados meteorológicos ou qualquer outro tipo de informação exposta por uma API.

Você também pode configurar seu próprio servidor externo para ajudar sua cena e sincronizar dados entre seus jogadores. Isso pode ser feito com um servidor que expõe uma API REST ou com um servidor que usa WebSockets.

## Chamar uma API REST

O código da sua cena pode enviar chamadas para uma API REST para buscar dados.

Como o servidor pode levar tempo para enviar sua resposta, você deve executar este comando como uma [função assíncrona](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/programming-patterns/async-functions.md), usando `executeTask()`.

```ts
executeTask(async () => {
	try {
		let response = await fetch(callUrl)
		let json = await response.json()
		console.log(json)
	} catch {
		console.log('falha ao alcançar a URL')
	}
})
```

O comando fetch também pode incluir um segundo argumento opcional que agrupa headers, método HTTP e corpo HTTP em um único objeto.

* **url**: Endereço para enviar a requisição
* **init**: Um `FlatFetchInit` objeto que pode conter:
  * **method** : Método HTTP a ser usado (GET, POST, DELETE, etc)
  * **body**: Conteúdo do corpo da requisição. Deve ser enviado como um objeto JSON transformado em string.
  * **headers**: Headers adicionais para incluir na requisição. Headers relacionados à assinatura são adicionados automaticamente.
  * **redirect**: Estratégia de redirecionamento ('follow' | 'error' | 'manual')
  * **responseBodyType**: Especifica se o corpo da resposta é 'text' ou 'json'
  * **timeout**: Quanto tempo esperar por uma resposta antes que a requisição falhe. Por padrão 30000 milissegundos (30 segundos).

```ts
executeTask(async () => {
	try {
		let response = await fetch(callUrl, {
			headers: { 'Content-Type': 'application/json' },
			method: 'POST',
			body: JSON.stringify(myBody),
		})
		let json = await response.json()
		console.log(json)
	} catch {
		console.log('falha ao alcançar a URL')
	}
})
```

O comando fetch retorna um `response` objeto com os seguintes dados:

* `headers`: Um `ReadOnlyHeaders` objeto. Chame o `get()` método para obter um header específico, ou o `has()` método para verificar se um header está presente.
* `ok`: Booleano
* `redirected`: Booleano
* `status`: Número do código de status
* `statusText`: Texto para o código de status
* `type`: Terá um dos seguintes valores: *basic*, *cors*, *default*, *error*, *opaque*, *opaqueredirect*
* `url`: URL que foi enviada
* `json()`: Obter o corpo em formato JSON.
* `text()`: Obter o corpo como texto.

{% hint style="warning" %}
**📔 Nota**: `json()` e `text()` são mutuamente exclusivos. Se você obtiver o corpo da resposta em um dos dois formatos, não poderá mais obter o outro a partir do `response` objeto.
{% endhint %}

{% hint style="warning" %}
**📔 Nota**: Cada cena Decentraland só tem permissão para executar um `fetch` comando por vez. Isso não afeta como o código da cena deve ser estruturado, pois as requisições são enfileiradas internamente. Se sua cena precisar enviar múltiplas requisições para endpoints diferentes, tenha em mente que cada requisição só é enviada quando a anterior recebeu resposta.
{% endhint %}

## Requisições assinadas

Você pode empregar uma medida extra de segurança para certificar que uma requisição se origina de uma sessão de jogador dentro do Decentraland. Você pode enviar suas requisições com uma assinatura adicional, que é assinada usando uma chave efêmera que a sessão Decentraland gera para cada jogador com base no endereço do jogador. O servidor que recebe a requisição pode então verificar se a mensagem assinada realmente corresponde a um endereço que está atualmente ativo no mundo.

Esse tipo de medida de segurança é especialmente valiosa quando pode haver um incentivo para um jogador abusar do sistema, para farmar tokens ou pontos em um jogo.

Para enviar uma requisição assinada, tudo o que você precisa fazer é usar o `signedFetch()` função, exatamente da mesma maneira que você usaria o `fetch()` função.

```ts
executeTask(async () => {
	try {
		let response = await signedFetch({
			url: callUrl,
			init: {
				headers: { 'Content-Type': 'application/json' },
				method: 'POST',
				body: JSON.stringify(myBody),
			},
		})

		if (!response.statusText) {
			throw new Error('Resposta inválida')
		}

		let json = await JSON.parse(response.statusText)

		console.log('Resposta recebida: ', json)
	} catch {
		console.log('falha ao alcançar a URL')
	}
})
```

A requisição inclui uma série adicional de headers, contendo uma mensagem assinada e um conjunto de metadados para interpretá-la. A mensagem assinada consiste em todo o conteúdo da requisição criptografado usando a chave efêmera do jogador.

O `signedFetch()` difere da `fetch()` função no sentido de que a resposta é uma promessa de uma mensagem http completa, expressa como um `FlatFetchResponse` objeto. Isto inclui as seguintes propriedades:

* `body`
* `headers`
* `ok`
* `status`
* `statusText`

determina quanta importância essa animação terá na média. **body** é considerada uma string, que você pode analisar como no exemplo acima. Se o corpo da resposta estiver em formato json, você pode especificar isso no `responseBodyType` e então acessar isso a partir da `json` propriedade na response.

### Validando uma requisição assinada

Para fazer uso de requisições assinadas, o servidor que as recebe deve validar que as assinaturas correspondem ao restante da requisição e que o timestamp codificado dentro da mensagem assinada está atual.

Você pode encontrar um exemplo simples de um servidor realizando essa tarefa na cena exemplo a seguir:

[Validar autenticidade do jogador](https://github.com/decentraland-scenes/validate-player-authenticity)

## Tempo limite da requisição

Se uma requisição HTTP demorar muito para ser respondida, ela falha para que outras requisições possam ser enviadas. Para ambos `fetch()` e `signedFetch()`, o limite de tempo padrão é de 30 segundos, mas você pode atribuir um valor diferente em cada requisição configurando a `timeout` propriedade em qualquer uma das duas funções. O valor de `timeout` é expresso em milissegundos.

```ts
fetch('https://some-url.com', { timeout: 1000 })
```

## Usar WebSockets

Você também pode enviar e obter dados de um servidor WebSocket, desde que esse servidor use uma conexão segura com *wss*.

```ts
var socket = new WebSocket('url')

socket.onmessage = function (event) {
	console.log('Mensagem WebSocket recebida:', event)
}
```

A sintaxe para usar WebSockets não difere da implementada nativamente pelo JavaScript. Veja a documentação da [Mozilla Web API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) para detalhes sobre como capturar e enviar mensagens por WebSockets.

{% hint style="info" %}
**💡 Tip**: Uma biblioteca que simplifica o uso de conexões websocket e que se mostrou funcionar muito bem com o Decentraland é [Colyseus](https://colyseus.io/). Várias outras bibliotecas websocket não são compatíveis com o SDK do Decentraland.

Ela constrói uma camada de abstração acima das conexões websocket que facilita reagir a mudanças e armazenar um estado de jogo consistente remotamente no servidor. Você pode vê-la em ação nestes exemplos:

* [Cube Jumper](https://github.com/decentraland-scenes/cube-jumper-colyesus-sdk7)
* [Space Traitor](https://github.com/decentraland-scenes/Space-Traitor)
* [AI NPC](https://github.com/decentraland-scenes/inworld-ai-sdk7)
  {% endhint %}

## Depuração de requisições de rede

Você pode depurar requisições de rede abrindo o Debug Panel.

Para abrir o Debug Panel, você pode clicar no ![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-92fe4dd70621a496d0da083ae9b5f9b2ef84d2dd%2Fdebug-icon.png?alt=media) ícone no canto superior direito. Então selecione a **Requisições Web** aba e clique **Abrir Chrome Devtools**.

Isso abrirá uma nova janela do Chrome com a aba Network aberta.

Veja [Depurar em preview](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/debugging/debug-in-preview.md#web-requests) para mais detalhes.
