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()
method call?Tara
02/15/2024, 1:13 PMAleksei Tirman [JB]
02/15/2024, 1:31 PMinstall(CORS) {
allowHost("localhost:3000")
}
The request looks like this:
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