Tara
02/14/2024, 9:26 PMTara
02/14/2024, 9:32 PMTara
02/14/2024, 9:32 PMpackage org.tatrc
import io.ktor.http.*
import io.ktor.serialization.gson.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.plugins.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.plugins.cors.*
import io.ktor.server.plugins.cors.routing.*
import io.ktor.server.plugins.cors.routing.CORS
import io.ktor.server.plugins.defaultheaders.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.netty.handler.codec.DefaultHeaders
import org.tatrc.plugins.*
var receivedName = Name( "unknown", "unknown" )
fun main() {
    //embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module).start(wait = true)
    val environment = applicationEngineEnvironment {
        connector {
            port = 8080
        }
        module(Application::module)
    }
    embeddedServer(Netty, environment).start(wait = true)
}
fun Application.module() {
    //configureHTTP()
    //configureSecurity()
    //configureRouting()
    routing {
        install(ContentNegotiation) {
            gson()
        }
        install(CORS) {
            allowHeader(HttpHeaders.ContentType)
            allowHeader(HttpHeaders.Authorization)
            allowHeader(HttpHeaders.AccessControlAllowOrigin)
            allowHeader(HttpHeaders.Origin)
/*
            allowHeader(HttpHeaders.Accept)
            allowHeader(HttpHeaders.AcceptCharset)
            allowHeader(HttpHeaders.AcceptEncoding)
            allowHeader(HttpHeaders.AcceptLanguage)
            allowHeader(HttpHeaders.AcceptRanges)
            allowHeader(HttpHeaders.Referrer)
            allowHeader("Access-Control-Request-Headers")
            allowHeader("Access-Control-Request-Method")
            allowHeader("Connection")
            allowHeader("DNT")
            allowHeader("Host")
            allowHeader("Referer")
            allowHeader("Sec-Fetch-Dest")
            allowHeader("Sec-Fetch-Mode")
            allowHeader("Sec-Fetch-Site")
            allowHeader("Sec-GPC")
            allowHeader("User-Agent")
allowHeader("Accept")
allowHeader("AcceptCharset")
allowHeader("Accept-Encoding")
allowHeader("Accept-Language")
allowHeader("AcceptRanges")
allowHeader("Age")
allowHeader("Allow")
allowHeader("ALPN")
allowHeader("AuthenticationInfo")
allowHeader("Authorization")
allowHeader("CacheControl")
allowHeader("Connection")
allowHeader("ContentDisposition")
allowHeader("ContentEncoding")
allowHeader("ContentLanguage")
allowHeader("ContentLength")
allowHeader("ContentLocation,")
allowHeader("ContentRange")
allowHeader("ContentType")
allowHeader("Cookie")
allowHeader("DASL")
allowHeader("Date")
allowHeader("DAV")
allowHeader("Depth")
allowHeader("Destination")
allowHeader("ETag")
allowHeader("Expect")
allowHeader("Expires")
allowHeader("From")
allowHeader("Forwarded")
allowHeader("Host")
allowHeader("HTTP2Settings")
allowHeader("If")
allowHeader("IfMatch")
allowHeader("IfModifiedSince")
allowHeader("IfNoneMatch")
allowHeader("IfRange")
allowHeader("IfScheduleTagMatch")
allowHeader("IfUnmodifiedSince")
allowHeader("LastModified")
allowHeader("Location")
allowHeader("LockToken")
allowHeader("Link")
allowHeader("MaxForwards")
allowHeader("MIMEVersion")
allowHeader("OrderingType")
allowHeader("Origin")
allowHeader("Overwrite")
allowHeader("Position")
allowHeader("Pragma")
allowHeader("Prefer")
allowHeader("PreferenceApplied")
allowHeader("ProxyAuthenticate")
allowHeader("ProxyAuthenticationInfo")
allowHeader("ProxyAuthorization")
allowHeader("PublicKeyPins")
allowHeader("PublicKeyPinsReportOnly")
allowHeader("Range")
allowHeader("Referrer")
allowHeader("Referer")
allowHeader("RetryAfter")
allowHeader("ScheduleReply")
allowHeader("ScheduleTag")
allowHeader("SecWebSocketAccept,")
allowHeader("SecWebSocketExtensions")
allowHeader("SecWebSocketKey")
allowHeader("SecWebSocketProtocol")
allowHeader("SecWebSocketVersion")
allowHeader("Server")
allowHeader("SetCookie")
allowHeader("SLUG")
allowHeader("StrictTransportSecurity")
allowHeader("TE")
allowHeader("Timeout")
allowHeader("Trailer")
allowHeader("TransferEncoding")
allowHeader("Upgrade")
allowHeader("UserAgent")
allowHeader("Vary")
allowHeader("Via")
allowHeader("Warning")
allowHeader("WWWAuthenticate")
allowHeader("AccessControlAllowOrigin")
allowHeader("AccessControlAllowMethods")
allowHeader("AccessControlAllowCredentials")
allowHeader("AccessControlAllowHeaders")
allowHeader("AccessControlRequestMethod")
allowHeader("AccessControlRequestHeaders")
allowHeader("AccessControlExposeHeaders")
allowHeader("AccessControlMaxAge")
allowHeader("XHttpMethodOverride")
allowHeader("XForwardedHost")
allowHeader("XForwardedServer")
allowHeader("XForwardedProto")
allowHeader("XForwardedFor")
allowHeader("XRequestId")
allowHeader("XCorrelationId")
            */
            allowHeader("*")
            allowMethod(HttpMethod.Get)
            allowMethod(<http://HttpMethod.Post|HttpMethod.Post>)
            allowMethod(HttpMethod.Put)
            allowMethod(HttpMethod.Delete)
            allowMethod(HttpMethod.Options)
            allowCredentials = true
            allowHost("localhost:3000", schemes = listOf("http"))
            allowHost("127.0.0.1:3000", schemes = listOf("http"))
            //anyHost()
        }
        //install(DefaultHeaders)
        val allowedOrigins = listOf("<https://your-frontend.com>")
        val allowedMethods = listOf(HttpMethod.Get, <http://HttpMethod.Post|HttpMethod.Post>)
        val allowedHeaders = listOf(HttpHeaders.ContentType, HttpHeaders.Authorization)
        get ("/") {
            call.respondText("Hello from Hello", ContentType.Text.Plain)
        }
        get("/submit_name") {
            val name = "Your name is ${receivedName.name} ${receivedName.surname}\n"
            call.respondText(name, ContentType.Text.Plain, status = HttpStatusCode.OK)
        }
        post("/submit_name") {
            println("---- POST submit_name")
            call.request.headers.forEach { s, strings ->
                println("---------- header $s: $strings")
            }
            val contentType = call.request.contentType()
            println("-------- contentType: $contentType")
            receivedName = when {
                //contentType.match(ContentType.Application.Json) -> call.receive<Name>()
                contentType.match(ContentType.Application.FormUrlEncoded) -> {
                    call.request.queryParameters.forEach { s, strings ->
                        println("---------- queryParam $s: $strings")
                    }
                    val name = call.request.queryParameters["name"] ?: "empty"
                    val surname = call.request.queryParameters["surname"] ?: "empty"
                    Name(name, surname)
                }
                contentType.match(ContentType.Text.Plain) -> Name( call.receiveText(), "" )
                else -> Name( "unknown", "type")
            }
            println("-------- receivedName: ${receivedName.name} ${receivedName.surname}")
            val response = "Hello, ${receivedName.name} ${receivedName.surname}!\n"
            val rtnContentType = ContentType.Text.Plain
            call.respondText(response, rtnContentType, status = HttpStatusCode.OK)
        }
        options("/submit_name") {
            println("---- OPTIONS submit_name")
            call.respond(HttpStatusCode.OK)
            /*
            call.request.headers.forEach { s, strings ->
                println("---------- header $s: $strings")
            }
            //val origin = call.request.origin // .origin.orElse("*")
            //if (origin in allowedOrigins || origin.startsWith("<http://localhost>")) {
                call.respondText(
                    "Allowed methods: ${allowedMethods.joinToString(", ")} \n" +
                            "Allowed headers: ${allowedHeaders.joinToString(", ")}",
                    ContentType.Text.Plain,
                    HttpStatusCode.OK
                )
            //} else {
            //    call.respond(HttpStatusCode.Forbidden)
            //}
             */
        }
    }
}
data class Name(val name: String, val surname: String)Tara
02/14/2024, 9:32 PMimport React, { useState } from 'react';
import { serverAddress } from '../config';
function SubmitNameForm() {
  const [name, setName] = useState('');
  const [surname, setSurname] = useState('');
  const [response, setResponse] = useState('');
  const [encodedBody, setEncodedBody] = useState('');
  const handleSubmit = async (event) => {
    event.preventDefault();
    try {
      //const bodyData = JSON.stringify({name, surname});
      //const bodyHeaders = "'Content-Type': 'application/json; charset=UTF-8'";
      const bodyData = 'name=' + name + '&surname=' + surname;
      //const bodyHeaders = "'Content-Type': 'text/plain'";
      const bodyHeaders = "'Content-Type': 'application/x-www-form-urlencoded'"
      const url = serverAddress + '/submit_name'
      setEncodedBody(url + '\n' + bodyData);
      const responseData = await fetch(url, {
        method: 'POST',
        headers: {
         bodyHeaders,
         'Access-Control-Allow-Origin': '*',
         'Origin': '<http://localhost:3000>'
        },
        body: bodyData,
        credentials: 'include',
      });
      const textResponse = await responseData.text();
      //const textResponse = await response.json();
      setResponse('Response: ' + textResponse);
    } catch (error) {
      console.error('Error submitting name:', error);
      //setResponse('An error occurred. Please try again.');
      if(error.response) {
            // The request was made and server responded with a status code
            // that falls out of the range of 2xx
            console.log(error.response.data);
            console.log(error.response.status);
            console.log(error.response.headers);
            setResponse('Response code: ' + error.response.status + ', headers: ' + error.response.headers);
      } else if(error.request) {
            // The request was made but no response was received
            console.log(error.request);
            setResponse('No response: ' + error.request);
      } else {
            // Something happened setting up request that triggered an Error
            console.log('Error', error.message);
            setResponse('Request setup: ' + error.message);
      }
    }
  };
  return (
    <form onSubmit={handleSubmit}>
      <p>
        <label htmlFor="name">Enter your name:</label>
        <input type="text" id="name" value={name} onChange={(e) => setName(e.target.value)} />
      </p><p>
        <label htmlFor="name">Enter your surname:</label>
        <input type="text" id="surname" value={surname} onChange={(e) => setSurname(e.target.value)} />
      </p>
      <button type="submit">Submit</button>
      <p>{response}</p>
      <p>Body {encodedBody}</p>
    </form>
  );
}
export default SubmitNameForm;Tara
02/14/2024, 9:32 PM// config.js
export const serverAddress = '<http://localhost:8080>';Tara
02/14/2024, 9:33 PMAndrew Kuryan
02/14/2024, 9:47 PMinstall(CORS) {
        anyHost()
        method(HttpMethod.Put)
        method(HttpMethod.Post)
        method(HttpMethod.Options)
        header(HttpHeaders.ContentType)
}Tara
02/14/2024, 9:57 PMTara
02/14/2024, 10:01 PMTara
02/14/2024, 10:02 PMAndrew Kuryan
02/14/2024, 10:04 PMAndrew Kuryan
02/14/2024, 10:08 PMTara
02/14/2024, 10:10 PMAleksei Tirman [JB]
02/15/2024, 7:40 AManyHost()Tara
02/15/2024, 1:13 PMAleksei Tirman [JB]
02/15/2024, 1:31 PMinstall(CORS) {
    allowHost("localhost:3000")
}fetch("<http://localhost:8000>", {
  method: "POST"
}).then((body) => body.text()).then((t) => console.log(t))Tara
02/15/2024, 7:32 PMAleksei Tirman [JB]
02/15/2024, 7:43 PMPOST /Tara
02/15/2024, 8:10 PMTara
02/15/2024, 11:03 PMTara
02/16/2024, 9:39 PM