# Swaggo with Fiber in Golang

In the last blog [post](https://firatkomurcu.com/building-and-validating-web-endpoints-with-fiber-in-golang), we talked about how we can create endpoints with the Fiber library. In this blog post, we will look at how we can integrate the Swagger into our Fiber endpoints with the Swaggo library.

Note: You can get the full source code from [here](https://www.youtube.com/redirect?event=video_description&redir_token=QUFFLUhqbklmX0g4bVhFRV9VT0lrd2l2TGlVLUhvMnZZUXxBQ3Jtc0treU91N2c3YlRtQ2xkZEdoR1ZKbnZtWnpDNUlrVFFaMDNPcDdqNDBJVnZ4OWZiQ0tzczVsb1BnbkZmTXBTYVh6XzA1YzltNndpeExIaWowbnF6VHJsb3hVR3drNzdndGN0M0xVVzNMbEFGRGFlOFp3RQ&q=https%3A%2F%2Fgithub.com%2FMehmetFiratKomurcu%2FYoutube-Channel%2Ftree%2Fmaster%2Fgolang-swaggo&v=m_8CjSQ0ZR8).

If you prefer to watch the video version of this blog post, here it is.

%[https://www.youtube.com/watch?v=m_8CjSQ0ZR8&t=14s&pp=ygULbWZrIGluIHRlY2g%3D] 

If you don't know what Swagger is, it is a UI that allows you to visualize and interact with the API’s resources. It is probably the most popular API documentation tool in the software world. Here is a [demo](https://petstore.swagger.io/?_ga=2.209648980.733451657.1707165885-1883968186.1707165884).

[Swaggo](https://github.com/swaggo/swag?tab=readme-ov-file#declarative-comments-format) is a library where you can generate swagger documentation with annotations. It can work with many web frameworks like Fiber and Gin.

To start, let's first download the Swaggo library.

```bash
go get -u github.com/swaggo/swag/cmd/swag
```

Now, we can run the `swag init` command in the Go project root folder, which contains `main.go` file.

```bash
swag init
```

Now you can see that there is a generated folder called docs, and there are files under it: docs.go, swagger.json, and swagger.yml. These are generated files with our annotations.

Now, we can download the Fiber Swaggo library.

```bash
go get -u github.com/gofiber/swagger
```

In order to make your Swagger doc work, you need to import Fiber Swagger and docs folder in `main.go`.

```go
import (
    "github.com/gofiber/swagger"
    _ "yt-swagger-go/docs" // yt-swagger-go is my project name
)
```

Looks like we are ready. First, let's put our API name in the documentation by adding annotations to our main function in `main.go` and add our swagger endpoint to see in the browser.

```go
//	@title			Order Api
//	@version		1.0
//	@description	This is an Order Api just for young people
//	@termsOfService	http://swagger.io/terms/
func main() {
    app := fiber.New()
    app.Get("/swagger/*", swagger.HandlerDefault)
    // code stuff
    app.Listen(":3000")
}
```

And now we can generate our swagger doc with `swag init` and `swag fmt`. `swag fmt` Checks spaces, etc. It is an optional command, and I just like to use it :)

Now, let's run our project and go to `localhost:3000/swagger/index.html` endpoint.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707166536798/1941d605-9e6e-4f8b-9fb1-d468f196abb3.png align="center")

And we can see our main doc headers in Swagger! Great!

Now, let's start to document our endpoints. We have one GET and one POST endpoint. We can start with the GET endpoint.

---

### Document GET Endpoint

Our endpoint is like this

```go
func GetOrderByCode(app *fiber.App) fiber.Router {
	return app.Get("/orders/code/:orderCode", func(ctx *fiber.Ctx) error {
		fmt.Printf("Your correlationId is %v", ctx.Locals("correlationId"))

		return ctx.SendString("This is your order Code: " + ctx.Params("orderCode"))
	})
}
```

This endpoint gets `orderCode` from the path, controls `correlationId` which we have a [middleware](https://github.com/MehmetFiratKomurcu/Youtube-Channel/blob/master/golang-swaggo/src/infra/middleware/correlation_id.go) that controls if it is null or not, and returns `orderCode` within a string. The annotations can be like this.

```go
// GetOrderByCode Getting Order by Code
//
//	@Summary		Getting Order by Code
//	@Description	Getting Order by Code in detail
//	@Tags			Orders
//	@Accept			json
//	@Produce		json
//	@Param			x-correlationid	header		string	true	"code of Order"
//	@Param			orderCode		path		string	true	"code of Order"
//	@Success		200				{string}	string
//	@Router			/orders/code/{orderCode} [get]
func GetOrderByCode(app *fiber.App) fiber.Router {
	return app.Get("/orders/code/:orderCode", func(ctx *fiber.Ctx) error {
		fmt.Printf("Your correlationId is %v", ctx.Locals("correlationId"))

		return ctx.SendString("This is your order Code: " + ctx.Params("orderCode"))
	})
}
```

**Summary**: Summary :)

**Description**: Detailed explanation of what this endpoint does.

**Tags**: How to group in swagger endpoints. I will talk about this later as well.

**Accept**: Accept request type

**Product**: Return request type

**Param**: This annotation gets more than one parameter. It is like this: param name, param [type](https://github.com/swaggo/swag?tab=readme-ov-file#param-type), [data type](https://github.com/swaggo/swag?tab=readme-ov-file#data-type), isMandatory, description(optional).

**Success**: Successful return status code and type

**Router**: URL and endpoint type (get, post, delete, etc.)

This is it for our first endpoint. Let's generate our swagger with `swag init`, and see the result in the browser.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707167463060/f6acb3c0-3ae4-4135-a005-7c222dbb28f1.png align="center")

Great, we can see our endpoint! Let's go to our POST endpoint.

---

### Document POST Endpoint

First, let's see what the endpoint looks like.

```go
func CreateOrder(app *fiber.App, customValidator *validation.CustomValidator) fiber.Router {
	return app.Post("/orders", func(ctx *fiber.Ctx) error {
		var request model.CreateOrderRequest
		err := ctx.BodyParser(&request)
		if err != nil {
			return err
		}

		if errs := customValidator.Validate(customValidator.Validator, request); len(errs) > 0 && errs[0].HasError {
			errorMessages := make([]string, 0)

			for _, err2 := range errs {
				errorMessages = append(errorMessages, fmt.Sprintf("%s field has failed. Validation is: %s", err2.Field, err2.Tag))
			}

			return ctx.Status(fiber.StatusBadRequest).JSON(strings.Join(errorMessages, " and that "))
		}

		return ctx.Status(fiber.StatusCreated).JSON("Order created successfully!")
	})
}
```

What this endpoint does? It is a POST endpoint, it gets a request from the body called `CreateOrderRequest` , parse it, validate the request, and if validation fails, returns `BadRequest`. If everything is good, return `Created` with a `string`.

Annotations would be like this.

```go
// CreateOrder Creating Order
//
//	@Summary		Creating Order
//	@Description	Creating Order with given request
//	@Tags			Orders
//	@Accept			json
//	@Produce		json
//	@Param			x-correlationid	header		string						true	"code of Order"
//	@Param			request			body		model.CreateOrderRequest	true	"Request of Creating Order Object"
//	@Success		200				{string}	string
//	@Failure		400				{string}	string	"Bad Request"
//	@Router			/orders [post]
func CreateOrder(app *fiber.App, customValidator *validation.CustomValidator) fiber.Router {
	// I am not showing here for keep the code snippet short.
}
```

Our Tag is still Orders, so it could be grouped with our GET endpoint. We have little new details in the annotations; let's look at them.

**Param** `body`: Now we are getting the request from the `body` and it is a custom `struct`, which we can write like `package.StructName`.

**Failure**: Fail return status code and type. (You didn't see that coming, right? :D)

Not let's run `swag init` and see our documentation.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707168031199/efb90e99-d9f4-4443-a044-f8d1d43a56f3.png align="center")

We have two order endpoints under the same group, thanks to `Tags` annotation. Let's open our POST endpoint.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707168096867/62eb7a91-a377-424a-bbd7-167c02a5c607.png align="center")

We can see `header`, our `CreateOrderRequest` object, and possible responses. Cool!

---

### Document Request Object

Sometimes, we can have complex request objects and want to explain further by property. We can do this with Swaggo. Let's try this on our `CreateOrderRequest` object.

```go
// CreateOrderRequest
// @Description Request about creating Order
type CreateOrderRequest struct {
	// shipment no of Order
	ShipmentNumber string `json:"shipmentNumber" validate:"required"`
	// country code like: tr, us
	CountryCode string `json:"countryCode" validate:"required,len=2"`
	// age to make sure you are young
	Age int `json:"age" validate:"required,oldAge"`
}
```

And here's the result of this. First `swag init` , then run the project again.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1707168269082/b2bba413-9a38-47fc-afe9-6aad36045418.png align="center")

There are a lot of annotations in Swaggo, and you can enrich the documentation of your APIs as much as you want.

Thanks for reading.

May the force be with you!
