Git Product home page Git Product logo

fking-locations's Introduction

fking-locations

Annotation library loooosely based on the Locations feature library from Ktor.

This library uses less annotation markup than my javalin-locations library, but instead requires pathing to declared as a parameter. This library replaces and deprecates javalin-locations as I believe it provides to quickest way to accomplish my own tasks, and it may be yours as well.

Targeting Javalin Version 4.X

<dependancy>
    <groupId>io.javalin</groupId>
    <artifactId>javalin</artifactId>
    <version>5.6.0</version>
</dependancy>

Accessible via MyMavenRepo

<repository>
    <id>fking.gay</id>
    <url>https://mymavenrepo.com/repo/gfyTmeWXHIH7EF6ijloQ/</url>
</repository>
<dependancy>
    <groupId>gay.fking.javalin</groupId>
    <artifactId>fking-locations</artifactId>
    <version>1.4.0</version>
</dependancy>

Basics

Javalin.create()
    .locations {
        // Routing here
    }.start(8080)

HTTP Method Handlers

When using fking-locations route handlers, you must define a class type that will be used for hydrating the incoming request, and passed to the handler as this.

/**
 * Without explicitly annotating class with @Hydrate all properties will be implicitly
 * hydrated, using path parameters, query parameters, and the request body.
 */
data class HelloWorld(val name: String? = null)

javalin.locations {
    /**
     * HTTP handler for GET request at index.
     */
    get<HelloWorld>("/") { ctx ->
        when {
            name.isNullOrBlank() -> ctx.result("Hello world!")
            else -> ctx.result("Hello, $name!")
        }
    }

    /**
     * HTTP handler for POST request at index.
     */
    post<HelloWorld>("/") {
        when {
            name.isNullOrBlank -> ctx.result("Hello world!")
            else -> ctx.result("Hello, $name!")
        }
    }
}

Hydration and Serialization

The fking-locations library by default implicitly hydrates properties on the provided request class. Meaning it will use path parameters, query parameters, form parameters and even the request body content to hydrate. To disable this feature explicitly mark class or property with the annotation @Hydrate.

Annotating a class with @Hydrate will disable all implicit hydration on its properties, and all properties must be marked with @Hydrate annotation to explicitly set hydration methods.

Leaving the annotation field @Hydrate.using blank, or as default, will be as if you have enabled implicit hydration on that property, or class.

Hydration Methods

  • IGNORED Hydration is disabled for this property.
  • PATH
  • QUERY
  • JSON_BODY
  • FORM_BODY
  • BODY (Includes any request body content; form, JSON, plain text, etc...)
/**
 * Defining class with annotation @Hydrate disabled implicit hydration.
 * This request will only hydrate using the request body content.
 */
@Hydrate(using = [HydrationMethod.BODY])
data class AuthenticationRequest(val username: String? = null, val password: String? = null)
/**
 * Class properties `title` and `body` will be hydrated using form body content.
 * Class property `category` will be hydrated using Javalin path properties.
 */
@Hydrate(using = [HydrationMethod.FORM_BODY])
data class PostTopicRequest(
    @Hydrate(using = [HydrationMethod.PATH]) val category: Int = -1,
    val title: String? = null,
    val body: String? = null
)

Pathing

The fking-locations library has several pathing methods for routing HTTP handlers, including nesting.

javalin.locations {
    // GET /
    get<Unit> { ctx ->
        ctx.result('Hello world')
    }

    path("/api/v1") {
        path("/authentication") {
            // POST /api/v1/authentication/login
            post<AuthenticationRequest>("/login") { ctx ->
                when {
                    username.isNullOrBlank() || password.isNullOrBlank() -> ctx.statusCode(400)
                        .result("Invalid request.")
                    else -> {
                        // etc...
                    }
                }
            }

            // POST /api/v1/authentication/refresh-token
            post<RefreshAccessTokenRequest>("/refresh-token") { ctx ->
                // etc...
            }
        }

        path("/topics") {
            // GET /api/v1/topics/{topicId}
            get<Topic>("/{topicId}") { ctx ->
                // etc
            }

            // POST /api/v1/topics
            post<CreateTopic> { ctx ->

            }
        }
    }

    path("/api/v2") {
        // HEAD /api/v2/status
        head<Unit>("status") { ctx ->
            ctx.status(200)
        }

        // /api/v2/topics
        path("/topics") {
            // etc...
        }
    }
}

All-Purpose Handler

You can create a generic handler that can handle one or more HTTP method(s).

javalin.locations {
    // GET, POST /api/v1/topic/{topicId}
    handle<Topic>("/api/v1/topic/{topicId}", HandlerType.GET, HandlerType.POST) { ctx ->
        // etc...
    }

    // Expand handler types example
    // GET, POST, HEAD, PUT /api/v1/topic/{topicId}
    handle<Topic>("/api/v1/topic/{topicId}", HandlerType.GET, HandlerType.POST, HandlerType.HEAD, HandlerType.PUT) { ctx ->
        // etc...
    }
}

Access Control

All handler methods supported an argument for permitted Javalin RouteRole implementations.

javalin.locations {
    handle<Topic>("/api/v1/topic/{topicId}", HandlerType.GET, HandlerType.POST, permittedRoles = arrayOf(ForumRole.GUEST, ForumRole.USER)) { ctx ->
        // etc...
    }

    // ANOTHER EXAMPLE
    post<Topic>("/api/v1/topic/{topicId}", permittedRoles = arrayOf(ForumRole.GUEST, ForumRole.USER)) { ctx ->
        // etc...
    }
}

Accessing Context from Request Class

You might want to write additional properties inside your request class that uses information from the current Context. You can gain access by extending the class ContextAwareRequest.

class SpecialRoute : ContextAwareRequest() {
    // context is available here as a protected property
    // IMPORTANT: context is only provided after hydration is complete
    // you will either have to use functions or val getters
    // or a lateinit exception will be thrown
    val authorizationToken
        get() = context.header("Authorization")
            .takeIf { !it.isNullOrEmpty() && it.startsWith("Bearer") }
            ?.substring(7)
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.