From d1f32e723af96bff68e0d3a6f1a0f39bb3efe14c Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Fri, 18 Sep 2020 13:58:31 +0300 Subject: [PATCH] minor improvements to the kafka-api example --- _examples/kafka-api/README.md | 16 +++ _examples/kafka-api/docker-compose.yml | 2 +- _examples/kafka-api/go.mod | 2 +- _examples/kafka-api/main.go | 17 +-- _examples/kafka-api/postman_collection.json | 137 ++++++++++++++++++++ 5 files changed, 162 insertions(+), 12 deletions(-) create mode 100644 _examples/kafka-api/postman_collection.json diff --git a/_examples/kafka-api/README.md b/_examples/kafka-api/README.md index c9db260f..ad82388f 100644 --- a/_examples/kafka-api/README.md +++ b/_examples/kafka-api/README.md @@ -12,6 +12,22 @@ Read the [code](main.go). $ docker-compose up ``` +### Troubleshooting + +On windows, if you get an error of `An attempt was made to access a socket in a way forbidden by its access permissions` + +Solution: + +1. Stop Docker +2. Open CMD with Administrator privileges and execute the following commands: + +```sh +$ dism.exe /Online /Disable-Feature:Microsoft-Hyper-V +$ netsh int ipv4 add excludedportrange protocol=tcp startport=2181 numberofports=1 +$ dism.exe /Online /Enable-Feature:Microsoft-Hyper-V /All +$ docker-compose up --build +``` + ## Manually Install & run Kafka and Zookeper locally and then: diff --git a/_examples/kafka-api/docker-compose.yml b/_examples/kafka-api/docker-compose.yml index 004c3ba0..e2e6dab6 100644 --- a/_examples/kafka-api/docker-compose.yml +++ b/_examples/kafka-api/docker-compose.yml @@ -10,7 +10,7 @@ services: ports: - 9092:9092 environment: - KAFKA_ADVERTISED_HOST_NAME: 10.122.1.109 # replace that with your own local ipv4 addr. + KAFKA_ADVERTISED_HOST_NAME: 10.122.1.142 # replace that with your own local ipv4 addr. KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 # kafka: # image: confluentinc/cp-kafka:5.5.0 diff --git a/_examples/kafka-api/go.mod b/_examples/kafka-api/go.mod index 2b5c1485..2ea93350 100644 --- a/_examples/kafka-api/go.mod +++ b/_examples/kafka-api/go.mod @@ -3,6 +3,6 @@ module myapp go 1.15 require ( - github.com/Shopify/sarama v1.26.4 + github.com/Shopify/sarama v1.27.0 github.com/kataras/iris/v12 master ) diff --git a/_examples/kafka-api/main.go b/_examples/kafka-api/main.go index 4d00e17a..4570b66c 100644 --- a/_examples/kafka-api/main.go +++ b/_examples/kafka-api/main.go @@ -3,7 +3,6 @@ package main import ( "encoding/json" "fmt" - "io/ioutil" "os" "strings" "time" @@ -86,8 +85,8 @@ func main() { app.Logger().Infof("Brokers: %s", strings.Join(brokers, ", ")) // GET : http://localhost:8080 // POST, GET: http://localhost:8080/api/v1/topics - // POST : http://localhost:8080/apiv1/topics/{topic}/produce?key=my-key - // GET : http://localhost:8080/apiv1/topics/{topic}/consume?partition=0&offset=0 + // POST : http://localhost:8080/api/v1/topics/{topic}/produce?key=my-key + // GET : http://localhost:8080/api/v1/topics/{topic}/consume?partition=0&offset=0 app.Listen(":8080") } @@ -138,7 +137,7 @@ func docsHandler(ctx iris.Context) { type httpError struct { Code int `json:"code"` - Reason string `json:"reason"` + Reason string `json:"reason,omitempty"` } func (h httpError) Error() string { @@ -226,10 +225,8 @@ func postTopicsHandler(ctx iris.Context) { return } - // unnecessary statement but it's here to show you that topic is created, - // depending on your API expectations and how you used to work - // you may want to change the status code to something like `iris.StatusCreated`. - ctx.StatusCode(iris.StatusOK) + ctx.StatusCode(iris.StatusCreated) + ctx.Writef("Topic %q created", t.Topic) } func getKafkaTopics() ([]string, error) { @@ -279,7 +276,7 @@ func postTopicProduceHandler(ctx iris.Context) { key := ctx.URLParamDefault("key", "default") // read the request data and store them as they are (not recommended in production ofcourse, do your own checks here). - body, err := ioutil.ReadAll(ctx.Request().Body) + body, err := ctx.GetBody() if err != nil { fail(ctx, iris.StatusUnprocessableEntity, "unable to read your data: %v", err) return @@ -347,7 +344,7 @@ func getTopicConsumeSSEHandler(ctx iris.Context) { } // `OnClose` fires when the request is finally done (all data read and handler exits) or interrupted by the user. - ctx.OnClose(func() { + ctx.OnClose(func(_ iris.Context) { ctx.Application().Logger().Warnf("a client left") // Close shuts down the consumer. It must be called after all child diff --git a/_examples/kafka-api/postman_collection.json b/_examples/kafka-api/postman_collection.json new file mode 100644 index 00000000..8f410573 --- /dev/null +++ b/_examples/kafka-api/postman_collection.json @@ -0,0 +1,137 @@ +{ + "info": { + "_postman_id": "8b135d95-ea8c-4dd5-a127-4b83cb735504", + "name": "iris-kafka-postman", + "description": "Postman API Requests for Iris + Kafka example", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Create Topic", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"topic\":\"mytopic\",\r\n \"partitions\": 1,\r\n \"replication\":1\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/api/v1/topics", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "topics" + ] + }, + "description": "Create a new kafka topic" + }, + "response": [] + }, + { + "name": "List all Topics", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/api/v1/topics", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "topics" + ] + }, + "description": "List all topics" + }, + "response": [] + }, + { + "name": "Store data to Topic", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"username\":\"kataras\",\r\n \"repo\":\"iris\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8080/api/v1/topics/mytopic/produce?key=mykey", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "topics", + "mytopic", + "produce" + ], + "query": [ + { + "key": "key", + "value": "mykey" + } + ] + }, + "description": "Produce some data to a Topic" + }, + "response": [] + }, + { + "name": "(Open in Browser) Consume data from a Topic", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:8080/api/v1/topics/mytopic/consume?partition=0&offset=0", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8080", + "path": [ + "api", + "v1", + "topics", + "mytopic", + "consume" + ], + "query": [ + { + "key": "partition", + "value": "0" + }, + { + "key": "offset", + "value": "0" + } + ] + }, + "description": "Note that, you have to open this one at your browser. Postman does not support SSE testing, see: https://github.com/postmanlabs/postman-app-support/issues/6682" + }, + "response": [] + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file