Skip to content

Commit

Permalink
Golem-Workers Swagger UI (#316)
Browse files Browse the repository at this point in the history
* initial swagger api

* navigatio

* better nav name

* redirectless json url

* Add option to overwrite spec requests url

* Add input to overwrite request URL

* Fix build issue

* pointers to api reference

* command to check the uvicorn logs

* openapi.json from main

---------

Co-authored-by: Phillip Jensen <phillip@golemgrid.com>
  • Loading branch information
mateuszsrebrny and cryptobench authored Sep 19, 2024
1 parent ea508f6 commit 035c3d2
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 9 deletions.
125 changes: 121 additions & 4 deletions src/components/SwaggerUI.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,139 @@
import { useState, useEffect, useCallback } from 'react'
import dynamic from 'next/dynamic'
import 'swagger-ui-react/swagger-ui.css'
import { ExclamationCircleIcon } from '@heroicons/react/20/solid'

const Swagger = dynamic(
() => import('swagger-ui-react').then((mod) => mod.default),
{ ssr: false }
)

export function SwaggerUI({ url, showInfo = false }) {
// Function to determine the class name based on the showInfo prop
export function SwaggerUI({
url,
showInfo = false,
overwrittenRequestURL: initialOverwrittenRequestURL = '',
}) {
const [overwrittenRequestURL, setOverwrittenRequestURL] = useState(
initialOverwrittenRequestURL || ''
)
const [isValidURL, setIsValidURL] = useState(true)
const [swaggerKey, setSwaggerKey] = useState(0)

useEffect(() => {
validateURL(overwrittenRequestURL)
console.log('overwrittenRequestURL updated:', overwrittenRequestURL)
setSwaggerKey((prev) => prev + 1) // Force re-render of Swagger component
}, [overwrittenRequestURL])

const validateURL = (input) => {
try {
new URL(input)
setIsValidURL(true)
} catch {
setIsValidURL(input === '')
}
}

const determineClass = (showInfo) => {
return showInfo ? '' : 'hide-info'
}

const className = determineClass(showInfo)

const requestInterceptor = useCallback(
(req) => {
console.log('Interceptor called with URL:', req.url)
console.log('Current overwrittenRequestURL:', overwrittenRequestURL)
if (req.url !== url && overwrittenRequestURL && isValidURL) {
const originalUrl = new URL(req.url)
const newUrl = new URL(overwrittenRequestURL)
newUrl.pathname = originalUrl.pathname
newUrl.search = originalUrl.search
req.url = newUrl.toString()
console.log('URL modified to:', req.url)
} else if (
req.url !== url &&
!overwrittenRequestURL &&
initialOverwrittenRequestURL
) {
const originalUrl = new URL(req.url)
const newUrl = new URL(initialOverwrittenRequestURL)
newUrl.pathname = originalUrl.pathname
newUrl.search = originalUrl.search
req.url = newUrl.toString()
console.log('URL modified to (using initial URL):', req.url)
}
return req
},
[url, overwrittenRequestURL, initialOverwrittenRequestURL, isValidURL]
)

const handleInputChange = (e) => {
const newValue = e.target.value
console.log('Input changed to:', newValue)
setOverwrittenRequestURL(newValue)
}

return (
<div className={`${className} not-prose`}>
<Swagger className="not-prose" url={url} />
<div className="space-y-4">
{initialOverwrittenRequestURL && (
<div>
<label
htmlFor="overwrittenRequestURL"
className="block text-sm font-medium leading-6 text-gray-900 dark:text-white"
>
SwaggerUI API Request URL
</label>
<div className="relative mt-2 rounded-md shadow-sm">
<input
id="overwrittenRequestURL"
name="overwrittenRequestURL"
type="url"
value={overwrittenRequestURL}
onChange={handleInputChange}
placeholder={`Enter API request URL (default: ${initialOverwrittenRequestURL})`}
className={`block w-full rounded-md border-0 px-2 py-1.5 pr-10 text-gray-900 ring-1 ring-inset ${
isValidURL
? 'ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600'
: 'text-red-900 ring-red-300 placeholder:text-red-300 focus:ring-2 focus:ring-inset focus:ring-red-500'
} dark:bg-slate-800 dark:text-white dark:ring-slate-700 dark:placeholder:text-slate-400 sm:text-sm sm:leading-6`}
aria-invalid={!isValidURL}
aria-describedby="url-error"
/>
{!isValidURL && (
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
<ExclamationCircleIcon
className="h-5 w-5 text-red-500"
aria-hidden="true"
/>
</div>
)}
</div>
{!isValidURL && (
<p
className="mt-2 text-sm text-red-600 dark:text-red-400"
id="url-error"
>
Please enter a valid URL (e.g., http://localhost:8000)
</p>
)}
<p className="mt-2 text-sm text-gray-500 dark:text-gray-400">
The author has specified {initialOverwrittenRequestURL} as the
default URL. If you&apos;re running the API on a different URL, you
can modify it here. This URL will be used for API requests instead
of the one specified in the OpenAPI spec.
</p>
</div>
)}
<div className={`${className} not-prose`}>
<Swagger
key={swaggerKey}
className="not-prose"
url={url}
requestInterceptor={requestInterceptor}
configUrl={null}
/>
</div>
</div>
)
}
1 change: 1 addition & 0 deletions src/markdoc/tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ const tags = {
selfClosing: true,
attributes: {
url: { type: String },
overwrittenRequestURL: { type: String },
showInfo: { type: Boolean },
},
},
Expand Down
1 change: 1 addition & 0 deletions src/navigation/docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ export const navigation = [
{ title: 'Create Node explained', href: '/docs/creators/golem-workers/create-node' },
{ title: 'Hello service example', href: '/docs/creators/golem-workers/hello-example' },
{ title: 'Stable Diffusion example', href: '/docs/creators/golem-workers/sd-example' },
{ title: 'API Reference', href: '/docs/creators/golem-workers/api-swagger-ui' },
{ title: 'Troubleshooting', href: '/docs/creators/golem-workers/troubleshooting' },
],
},
Expand Down
21 changes: 21 additions & 0 deletions src/pages/docs/creators/golem-workers/api-swagger-ui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
description: OpenAPI documentation for the Golem-Workers service, detailing endpoints, request parameters, and response formats.
title: Golem-Workers API
type: Swagger
---

## Golem-Workers API Documentation

This page provides OpenAPI documentation for the Golem-Workers API.
Use the interactive Swagger UI below to explore the available endpoints,
request parameters, and response formats.
You can test the API by sending requests directly from the UI,
making it easier to understand and integrate the Golem Reputation Service into your applications.

Note: The interactive API reference uses your own Golem-Workers service,
typically running at **localhost:8000**.
For instructions on how to set it up, check out the
[Getting Started](/docs/creators/golem-workers/getting-started) guide.

{% swaggerui showInfo=false url="https://raw.githubusercontent.com/golemfactory/golem-workers/main/openapi.json" overwrittenRequestURL="http://localhost:8000" /%}

3 changes: 2 additions & 1 deletion src/pages/docs/creators/golem-workers/basic-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ explaining how to manage clusters and nodes and interact with the Golem Network.

To start, access the built-in API documentation provided by the Golem-Workers server
([Getting Started](/docs/creators/golem-workers/getting-started) explains how to start it).
The documentation is auto-generated and available by default at [http://localhost:8000/docs](http://localhost:8000/docs).
The documentation is auto-generated and available by default at [http://localhost:8000/docs](http://localhost:8000/docs)
(and also in the [API Reference](/docs/creators/golem-workers/api-swagger-ui) section of this documentation).

This interface is a useful resource for understanding:
- **Schemas**: Detailed structure of the API requests and responses.
Expand Down
3 changes: 2 additions & 1 deletion src/pages/docs/creators/golem-workers/create-node.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ This section will walk through its configurable aspects but do not hesitate to
consult the Open API spec for more details.
It is provided by the Golem-Workers server
([Getting Started](/docs/creators/golem-workers/getting-started) explains how to start it).
The documentation is auto-generated and available by default at [http://localhost:8000/docs](http://localhost:8000/docs).
The documentation is auto-generated and available by default at [http://localhost:8000/docs](http://localhost:8000/docs)
(and also in the [API Reference](/docs/creators/golem-workers/api-swagger-ui) section of this documentation).

## Node Creation Options

Expand Down
3 changes: 2 additions & 1 deletion src/pages/docs/creators/golem-workers/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ The next steps:
running a simple service on the Golem Network testnet
- Checkout the advanced [Stable Diffusion example](/docs/creators/golem-workers/sd-example) to see an example of
running `automatic1111` on Golem Network GPU nodes
- Play with [OpenAPI specification](http://localhost:8000/docs) - it hosts plenty illustrative examples,
- Play with [OpenAPI specification](/docs/creators/golem-workers/api-swagger-ui)
(also available directly at [http://localhost:8000/docs](http://localhost:8000/docs)) - it hosts plenty illustrative examples,
and formally describes the schemas

4 changes: 3 additions & 1 deletion src/pages/docs/creators/golem-workers/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ with the Golem Network.
- [Hello service example](/docs/creators/golem-workers/hello-example) step-by-step tutorial of renting a node and using it
for a super simple Hello service
- [Stable Diffusion example](/docs/creators/golem-workers/sd-example) step-by-step tutorial of renting a mainnnet GPU node
and using it for Stable Diffusion
and using it for Stable Diffusion
- [API Reference](/docs/creators/golem-workers/api-swagger-ui) clickable formally described endpoints and schemas,
with ilustrative examples
3 changes: 2 additions & 1 deletion src/pages/docs/creators/golem-workers/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ To continuously view new logs as they are generated, use the `-f` or `--follow`

{% problem /%}

The `create-node` endpoint may occasionally fail. When this happens, it can be helpful to check the Uvicorn logs.
The `create-node` endpoint may occasionally fail. When this happens, it can be helpful to check the Uvicorn logs
(`docker compose logs web` command).
You might encounter a stacktrace that mentions **'NoneType' object is not iterable**.

{% solution %}
Expand Down

0 comments on commit 035c3d2

Please sign in to comment.