I'm looking for a way to configure https for Ktor application.
I've found an official documentation there:
https://ktor.io/servers/self-signed-certificate.html
Here explained how to add links to certs inside the HOCON config file.
Is it possible to config ssl without config file?
Here's my codebase:
http = embeddedServer(Netty, port = listenPort, configure = {
connectionGroupSize = 1
workerGroupSize = 5
}){
if(sslCertificate != null) {
install(HttpsRedirect) {
sslPort = 443
}
}
install(StatusPages) {
exception<NotFoundError> { cause ->
logger.error("NotFoundError:", cause.message)
call.respondText(cause.message ?: "",
ContentType.Text.Plain, HttpStatusCode.NotFound){}
}
exception<BadFormatError> { cause ->
logger.error("BadFormatError:", cause.message)
call.respondText(cause.message ?: "",
ContentType.Text.Plain, HttpStatusCode.BadRequest){}
}
exception<UserMistake> { cause ->
logger.error("UserMistake:", cause.message)
call.respondText(cause.message ?: "",
ContentType.Text.Plain, HttpStatusCode.BadRequest){}
}
exception<OverloadedException> { cause ->
logger.error("OverloadedException:", cause.message)
call.respondText(cause.message ?: "",
ContentType.Text.Plain, HttpStatusCode.ServiceUnavailable){}
}
exception<Exception> { cause ->
logger.error("Exception:", cause.message)
call.respondText(cause.message ?: "",
ContentType.Text.Plain, HttpStatusCode.InternalServerError){}
}
}
intercept(ApplicationCallPipeline.Call) {
call.response.headers.append(HttpHelper.ACCESS_CONTROL_ALLOW_ORIGIN, "*")
call.response.headers.append(HttpHelper.ACCESS_CONTROL_REQUEST_METHOD, "POST, GET, OPTIONS")
// call.response.headers.append(HttpHelper.CONTENT_TYPE, "application/json")
if(call.request.uri.endsWith("/")) {
call.respondRedirect(call.request.uri.dropLast(1))
}
}
}
http.start()
It's a bit complex, but possible. You configure this using sslConnector in the environment:
fun main() {
val environment = applicationEngineEnvironment {
log = LoggerFactory.getLogger("ktor.application")
// Here you can the key store and keys configuration
sslConnector(keyStore, ...)
module(Application::myModule)
}
embeddedServer(Netty, environment, configure = {
// ...
})
}
fun Application.myModule() {
}
Related
i am facing problem to give provider name because i dont know how to give proper provider in swifter.authorize
my controller is where i am using login code
you can check func actiontwitter in which i have used provider then please suggest me how to use provider as parameter
i have installed swifter package in project
//
// twitterVc.swift
// socialLogin
//
// Created by ios on 19/11/22.
//
import UIKit
import FirebaseAuth
import Swifter
import SafariServices
struct TwitterConstants {
static let CONSUMER_KEY = "MY_CONSUMER_KEY"
static let CONSUMER_SECRET_KEY = "MY_CONSUMER_SECRET_KEY"
static let CALLBACK_URL = "MY_CALLBACK_URL"
}
class twitterVc: UIViewController {
var swifter: Swifter!
var accToken: Credential.OAuthAccessToken?
#IBOutlet weak var submitBtn: UIButton!
var provider = OAuthProvider(providerID: "twitter.com")
override func viewDidLoad() {
super.viewDidLoad()
self.isLoggedIn { loggedin in
if loggedin {
// Show the ViewController with the logged in user
print("Logged In?: YES")
} else {
// Show the Home ViewController
print("Logged In?: NO")
}
}
}
func isLoggedIn(completion: #escaping (Bool) -> ()) {
let userDefaults = UserDefaults.standard
let accessToken = userDefaults.string(forKey: "oauth_token") ?? ""
let accessTokenSecret = userDefaults.string(forKey: "oauth_token_secret") ?? ""
let swifter = Swifter(consumerKey: TwitterConstants.CONSUMER_KEY, consumerSecret: TwitterConstants.CONSUMER_SECRET_KEY, oauthToken: accessToken, oauthTokenSecret: accessTokenSecret)
swifter.verifyAccountCredentials(includeEntities: false, skipStatus: false, includeEmail: true, success: { _ in
// Verify Succeed - Access Token is valid
completion(true)
}) { _ in
// Verify Failed - Access Token has expired
completion(false)
}
}
#IBAction func actionSubmit(_ sender: Any) {
self.actionTwitter()
}
func actionTwitter(){
//~~~~~~~~~~~~~~problem is here it is not taking provider as parameter
self.swifter.authorize(withProvider: provider as! ASWebAuthenticationPresentationContextProviding, callbackURL: URL(string: TwitterConstants.CALLBACK_URL)!) { (tokan: Credential.OAuthAccessToken?, resp: URLResponse) in
}
}
}
func failureHandler(){
}
extension twitterVc: SFSafariViewControllerDelegate{
func getUserProfile() {
self.swifter.verifyAccountCredentials(includeEntities: false, skipStatus: false, includeEmail: true, success: { json in
let userDefaults = UserDefaults.standard
userDefaults.set(self.accToken?.key, forKey: "oauth_token")
userDefaults.set(self.accToken?.secret, forKey: "oauth_token_secret")
// Twitter Id
if let twitterId = json["id_str"].string {
print("Twitter Id: \(twitterId)")
} else {
// self.twitterId = "Not exists"
}
// Twitter Handle
if let twitterHandle = json["screen_name"].string {
print("Twitter Handle: \(twitterHandle)")
} else {
// self.twitterHandle = "Not exists"
}
// Twitter Name
if let twitterName = json["name"].string {
print("Twitter Name: \(twitterName)")
} else {
// self.twitterName = "Not exists"
}
// Twitter Email
if let twitterEmail = json["email"].string {
print("Twitter Email: \(twitterEmail)")
} else {
// self.twitterEmail = "Not exists"
}
// Twitter Profile Pic URL
if let twitterProfilePic = json["profile_image_url_https"].string?.replacingOccurrences(of: "_normal", with: "", options: .literal, range: nil) {
print("Twitter Profile URL: \(twitterProfilePic)")
} else {
// self.twitterProfilePicURL = "Not exists"
}
print("Twitter Access Token: \(self.accToken?.key ?? "Not exists")")
}) { error in
print("ERROR: \(error.localizedDescription)")
}
}
}
Trying to figure out, how to use multiple karate-config.js and karate-config-.js file
like below File 1: karate-congig.js
function fn() {
var env = karate.env; // get system property 'karate.env'
karate.log('karate.env system property was:', env);
if (!env) {
env = 'dev';
}
var config = {
}
if (env == 'dev') {
// customize
// e.g. config.foo = 'bar';
} else if (env == 'e2e') {
// customize
}
return config;
}
File 2: karate-config-SysVar.js
function fn() {
var config = {
dbUserName : 'UserName',
dbPassword : 'password',
HostURL : 'URL'
}
return config;
}
Tried to refer this documentation: https://github.com/karatelabs/karate#environment-specific-config
And example Not Found https://github.com/karatelabs/karate/blob/master/karate-demo/src/test/java/karate-config-contract.js
Thanks in Advance
import SwiftUI
struct ReserveView: View {
#State var searchT = ""
#State var isSearching = false
#State private var showCheckAlert = false
#Binding var roomnum:Int
#StateObject private var vm = ReserveViewModel(
service: ReserveService()
)
var body: some View {
VStack{
HStack{
TextField("Search", text:$searchT)
.padding(.leading, 30)
}
.padding()
.background(Color.gray.opacity(0.2))
.cornerRadius(6)
.padding(.horizontal)
.onTapGesture(perform: {
isSearching = true
})
.overlay(
HStack {
Image(systemName: "magnifyingglass")
Spacer()
}.padding(.horizontal,32)
.foregroundColor(.white)
)
if isSearching {
Button(action:{
isSearching = false
searchT = ""
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for:nil)
}, label: {
Text("Cancle")
.padding(.trailing)
.padding(.leading,0)
})
.transition(.move(edge: .trailing))
}
switch vm.state{
case .success(let data):
List{
ForEach((data).filter({"\($0)".contains(searchT)||searchT.isEmpty}),
id: \.roomnum){ item in
HStack{
Text("\(item.when) \(item.time) \(item.username)").foregroundColor(Color.black)
}
}
}
.padding(.bottom,15)
//.padding(.top,20)
case .loading:
ProgressView()
default:
EmptyView()
}
}
.task {
await vm.getReserves()
}
}
}
struct ReserveView_Previews: PreviewProvider {
static var previews: some View {
ReserveView(roomnum:.constant(""))
}
}
import Foundation
import SwiftUI
struct ReserveService {
enum ReserveListError: Error {
case failed
case failedToDecode
case invalidStatusCode
}
func fetchReserves() async throws -> [Reserve] {
let url = URL(string: "https://f6d3-119-203-102/roomreserveview?roomnum=\(here i want use variable)")!
let configuration = URLSessionConfiguration.ephemeral
print(url)
let (data, response) = try await URLSession(configuration: configuration).data(from: url)
guard let response = response as? HTTPURLResponse,
response.statusCode == 200 else{
throw ReserveListError.invalidStatusCode
}
let decodedData = try JSONDecoder().decode(ReserveServiceResult.self, from: data)
return decodedData.reserveInfo
}
}
import SwiftUI
import Foundation
#MainActor
class ReserveViewModel: ObservableObject {
enum State {
case na
case loading
case success(data: [Reserve])
case failed(error: Error)
}
#Published private(set) var state: State = .na
#Published var hasError: Bool = false
private let service: ReserveService
init(service: ReserveService) {
self.service = service
}
func getReserves() async {
self.state = .loading
self.hasError = false
do {
let reserves = try await service.fetchReserves()
self.state = .success(data: reserves)
}catch {
self.state = .failed(error: error)
self.hasError = true
print(String(describing: error))
}
}
}
hello! I'd like to ask you a SwiftUI question.
Based on the ReserveService file, I am implementing the part that lists and displays the desired data in ReserveView.
I want to complete the url in the 'fetchReserves' function by receiving the variable 'roomnum' from the ReserveView model to the ReserveService.
However, Binding does not seem to work because ReserveService is not a view model. Is there any way I can get this variable from the viewmodel?
If you don't understand my explanation, please ask the question again.
This is my first time asking a question. Please forgive me if there is something missing in my question
It is possible to inject it as function argument, like
func fetchReserves(_ roomnum: Int) async throws -> [Reserve] {
let url = URL(string:
"https://f6d3-119-203-102/roomreserveview?roomnum=\(roomnum)")!
I am new to kotlin, so I am sorry in advance, if this is a simple misstake.
I am trying at the moment to rewrite an api (written in Kotlin) to java 17.
Everything worked so far. But now I am getting following deprecated message:
'toLowerCase(): String' is deprecated. Use lowercase() instead.
Of course I know what it means, so I tried doing it like in the following Picture:
https://i.stack.imgur.com/vT8k5.png
But why doesnt it find the lowercase Function?
This is in my build.gradle:
plugins {
id 'org.jetbrains.kotlin.jvm'
id "org.jetbrains.kotlin.kapt"
id "org.jetbrains.dokka"
id "java-library"
id "maven-publish"
id "jacoco"
id "io.gitlab.arturbosch.detekt"
id "org.jlleitschuh.gradle.ktlint"
id "com.github.gmazzo.buildconfig"
}
apply from: "${rootDir}/gradle/dependencies.gradle"
tasks.withType(org.jetbrains.dokka.gradle.DokkaTask).configureEach {
dokkaSourceSets {
configureEach {
sourceLink {
localDirectory.set(file("src/main/kotlin"))
remoteUrl.set(uri("").toURL())
}
externalDocumentationLink { url.set(new URL("https://square.github.io/retrofit/2.x/retrofit/")) }
externalDocumentationLink { url.set(new URL("https://square.github.io/okhttp/3.x/okhttp/")) }
externalDocumentationLink { url.set(new URL("https://square.github.io/moshi/1.x/moshi/")) }
}
}
}
tasks.dokkaJavadoc.configure {
outputDirectory.set(javadoc.destinationDir)
}
task sourceJar(type: Jar) {
archiveClassifier = "sources"
from sourceSets.main.allSource
}
task javadocJar(type: Jar, dependsOn: dokkaJavadoc) {
archiveClassifier = "javadoc"
from javadoc.destinationDir
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = "17"
allWarningsAsErrors = true
freeCompilerArgs = ["-Xjsr305=strict", "-progressive"]
}
}
kapt {
useBuildCache = true
}
test {
finalizedBy jacocoTestReport
useJUnitPlatform()
}
buildConfig {
packageName("my.package") // forces the package. Defaults to '${project.group}'
useKotlinOutput() // adds `internal` modifier to all declarations
buildConfigField("String", "packageName", "\"my.package\"")
buildConfigField("String", "version", provider { "\"${project.version}\"" })
}
jacoco {
setToolVersion(jacocoVersion)
}
jacocoTestReport {
reports {
xml.required = true
html.required = false
}
}
ktlint {
disabledRules = ["import-ordering"]
version = ktlintVersion
reporters {
reporter "checkstyle"
}
}
detekt {
version = detektVersion
buildUponDefaultConfig = true
config = files("$rootDir/config/detekt.yml")
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}
compileKotlin {
kotlinOptions {
jvmTarget = "17"
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = "17"
}
}
Ensure your kotlin-stdlib version is 1.5 or above. Check this out
I have setup server according to docs and try to upload file using code from this question:
val parts: List<PartData> = formData {
append(
"image",
InputProvider { ins.asInput() },
Headers.build {
this[HttpHeaders.ContentType] = "image/png"
this[HttpHeaders.ContentDisposition] = "filename=$name"
}
)
}
return HttpClient(Apache) {
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
}
}.submitFormWithBinaryData(formData = parts) {
url("$baseUrl/images")
}
If I use it as is (without request Content-Type), then server fails: "Content-Type header is required for multipart processing".
If I try to add header, client fails: "Header Content-Type is controlled by the engine and cannot be set explicitly".
Then it's actually something strange happening.
According to client logs, it's sending content type:
REQUEST: http://localhost:8090/images
METHOD: HttpMethod(value=POST)
COMMON HEADERS
-> Accept: */*
-> Accept-Charset: UTF-8
CONTENT HEADERS
BODY Content-Type: multipart/form-data; boundary=-675255df42a752ee167beaab-5799548c6088f411-a7e8dc449d68ab028c44d80-42b
BODY START
[request body omitted]
...
But on server side headers are completly different:
Accept-Charset [UTF-8]
Accept [*/*]
User-Agent [Ktor client]
Transfer-Encoding [chunked]
Host [localhost:8090]
Connection [Keep-Alive]
On other hand I can successfully upload file using okhttp (and headers actually matches):
val logging = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String ) {
println(message)
}
})
logging.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(logging)
.build()
val file = File("image.png")
val part: MultipartBody.Part = MultipartBody.Part.Companion.createFormData(
"image",
"image.png",
file.asRequestBody("image/png".toMediaTypeOrNull())
)
val request = Request.Builder()
.url("http://localhost:8090/images")
.post(MultipartBody.Builder().addPart(part).build())
.build()
val res = client.newCall(request).execute()
res.body
Is it bug in ktor client or I missing something?
edit:
Both client and server versions is 1.4.1.
Corresponding gradle dependencies parts:
implementation("io.ktor:ktor-server-core:${ktor_version}")
implementation("io.ktor:ktor-server-netty:${ktor_version}")
implementation("io.ktor:ktor-jackson:$ktor_version")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.8")
...
implementation("io.ktor:ktor-client-core:$ktor_version")
implementation("io.ktor:ktor-client-cio:$ktor_version")
implementation("io.ktor:ktor-client-jackson:$ktor_version")
implementation("io.ktor:ktor-client-logging:$ktor_version")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.2")
route:
object ImagesRouter {
fun Routing.images(imagesModule: ImagesModule) {
route("images") {
get("/{id}") {
// ...
}
post {
val multipart = call.receiveMultipart() // fails here
// ...
}
}
}
}