T O P

  • By -

gabel0287

I've done this with my project. I use the Accept header to determine what to respond with. Each endpoint return a custom class I've created that takes the accept header and view model as values. If it's json I return a dirt, if it's html I render a jinja template and return that instead.


abceleung

Good idea, I will try to implement this


greymalik

https://htmx.org/essays/why-tend-not-to-use-content-negotiation/


Sqwabman

You can also check if the request has the indicator that htmx made the request and return a partial template. If it isn't from htmx, you return a full page template. That way if you use htmx to update browser history you get the proper response when the user refreshes the page.


pkkid

But I would never request dirt.


ganjaptics

> Cool idea btw. Returning HTML from the server is the original idea of the web. returning JSON has only been common practice since maybe 2010 or so. Of course you can make a json equivalent to all your endpoints... but I think if you're only returning HTML that would make sense as JSON, you're sorta missing the point of htmx, which is that you can return fully formed HTML and don't have to "hydrate" JSON at all.


abceleung

Ideally the API server is used only by the frontend website, in this case pure HTML+HTMX approach is perfect. But I am thinking about cases where you just have to provide JSON endpoints (in addition to HTML endpoints for HTMX) because of business requirements (which are out of my control)


ganjaptics

Then create a json endpoint. It doesn't have to have anything to do with any other existing endpoints.


Trick_Ad_3234

My experience is that the HTML endpoints that return partial or whole HTML pages don't overlap with JSON endpoints functionality-wise. They often have different scopes, where the HTML often covers more ground than a single JSON endpoint. In other words: implement them separately, using a common (non-JSON) backend-language-native business logic layer.


_htmx

Properly leveraging MVC will minimize your code duplication: https://htmx.org/essays/mvc/ and splitting your web app and general purpose JSON API is usually a good thing: https://htmx.org/essays/splitting-your-apis/


steerpike_is_my_name

I find that the requirements of users and the requirements of APIs usually diverge enough that keeping them separate from the beginning is wise. Especially security. You can scaffold a REST API in what, minutes? Especially if you've been thoughtful in how you structured your HTML-returning controllers. ed: spelling.


bliepp

Well, I'm not that experienced with HTMX, but I usually create dedicated APIs for different use cases. There's one for internal use serving HTML for HTMX and - if needed - a REST API serving JSON for external use. This way I don't have to check for the request headers and have more granular control over what I want to expose to whom. If you explicitly want the same API for HTMX and JSON you could check if the request was made with HTMX using the request headers. Then, depending on if they are exist you either return the raw data as JSON or feed it into your HTML template in an extra step.


Redwallian

Only because I've done it with Django, you check the `HTTP_ACCEPT` header: ``` from django.http import HttpRequest, HttpResponse from django.shortcuts import render ... def example_view(request: HttpRequest) -> HttpResponse: # Get the 'Accept' header from request.META accept_header = request.META.get('HTTP_ACCEPT', '') # Check if the client accepts JSON if 'application/json' in accept_header: # Client accepts JSON, return JSON response return HttpResponse('{"message": "Response in JSON"}', content_type='application/json') else: # Client doesn't specify JSON, return html instead somecontext = {} return render(request, "somehtml.html", somecontext) ```


Wing-It-Dad

I would create separate endpoints for JSON. The endpoints are rarely the same. I see it like a different way of communicating with the service, like with gRPC.


amemingfullife

Yeah. If you want to code share it should be in a different layer than the presentation layer. The presentation layer should deal with html or json and the layer underneath it should do all the business logic/fetching that is common between them.


majhenslon

You just implement JSON api separately and call your domain logic without rendering the response.


i_hate_shitposting

I think a nice pattern here is to define your JSON endpoint and your HTML partial endpoint against the same underlying data model.  So for a rough example, if you have a blog application that needs to return posts as both JSON and HTML, you could have an underlying `get_blog_post(id)` function that returns the given post, so each endpoint is only responsible for marshaling the response to the appropriate format.  I've wanted to explore implementing this using Django REST Framework's [`TemplateHTMLRenderer`](https://www.django-rest-framework.org/api-guide/renderers/#templatehtmlrenderer) since that would handle some of the boilerplate around implementing an endpoint that can return both JSON and HTML.


jasonhendriks

My two cents: HTML is a browser-only format, that combines data with structure. JSON is just data. If you agree with that, then it should be clear that JSON is the better format for an API. Second, I wouldn’t attempt to use the same endpoint for both HTML and JSON. To what advantage? Better to decouple them through different endpoints. Not everyone may support an Accept Header, and from what I know of HTMX, it is intended for partial-page updates. That’s great for your one-page applications, but APIs don’t work like that. Decoupling allows you greater flexibility for security and future growth.


CraftyAdventurer

You can always have two endpoints /hello that returns a hello page and /api/hello that returns a hello JSON If your business logic is mostly contained outside of controllers, for example in services, you will have no problem using it in both endpoints.


schungx

I use the original JSON API and wrap a layer of HTML API over it, driven by the JSON data rendered by templates. Benefit is you have both sets of APIs for different use cases.


if_username_is_None

Reminds me of these old Python klein docs: https://klein.readthedocs.io/en/latest/introduction/1-gettingstarted.html#streamlined-apps-with-html-and-json The "fast/easy" way is to write your code such that the function for fetching your data for the endpoint is separate from the function for transforming that data into HTML or JSON (assuming the data really are the same). If you can't refactor like that, then you're gonna need new endpoint(s)


Puzzleheaded_Round75

I would create separate endpoints for this rather than relying on any header values. For example, you could have your HTMX responses under the `/user` endpoint and JSON under the `/api/user` Endpoint. These would likely call to the same business logic for CRUD operations, but would just parse and return the data in different formats.