I've noticed that when using `returnFormat=json` o...
# cfml-general
a
I've noticed that when using
returnFormat=json
on a remote method in a cfc, the content type is still HTML. shouldn't everything with
returnFormat=json
return it with the correct response header ?
and how can I implement the above
b
The CF engines have different implementations here
Start by telling us which CF engine you're on
Also, are you overriding the content type in your own CF code, because that will always win
a
i'm on CF2021
I'm not, no
I'm happy to do that, but I feel it should do it anyway
b
I would guess you are and don't realize it
Put in some debugging to find out
and top and bottom of your custom CFC remote method, output the response content-type header to see what it is
a
hm not sure where to start
I'm just returning an object
function builds an object then returns it
that's it
using the
return
syntax
b
You're not calling any other services or frameworks?
a
nope
get data from a datbase, format it, return it
b
I tried to whip up an example of spying on the response content type header, but it only seems to work in Lucee 🤔 Adobe must be doing something different under the hood 😕
Copy code
writeDump( getPageContext().getResponse().getHeader("Content-Type") )
cfheader( name="Content-Type", value="text/html" );
writeDump( getPageContext().getResponse().getHeader("Content-Type") )
a
this has always been the case for me
I just thought the browser wasn't formatting it for some reason
but it's due to that. I've manually set the content type on this particular function and it looks lovely now
b
Also, when you say the response has an HTML content type, can you confirm in your browser's debugging console it's actually there
And you weren't inferring that just from the way it rendered
a
but I'd like it to do it whenever
returnFormat=json
really is set
b
I have seen browsers cache content types before, but not recently.
a
it's actually there yes
👍 1
it's just rendered as html
I'm consuming it and it works fine
b
So you were seeing this?
a
exactly
luckily the 'preview' pane of the response in devtools formatted it to json for me
top request,
getChannels
doesn't have the cfheader set in the function
has given it a different icon too
b
I can't say I've seen that then
b
@Alan, you say, "I'm just returning an object". Question is, what kind of object is it? What is the function's
returntype
? That is perhaps the crux of the matter. ColdFusion usually makes a guess as to the return format. For example, should the returned object be a struct, ColdFusion would return a JSON by default. That is, whether you specify
returnformat
or not. It might be that, in your case, ColdFusion cannot workout what the
returntype
is or cannot convert the returned object to JSON.
a
the return type is
struct
and it only returns it as json if
returnFormat=json
is specified
otherwise it returns it as an object. where I can see
<struct>
for example in the markup
CF definitely won't default it to json
returnFormat=json
works fine. It's just the response content type is wrong
b
Ah, I see. I thought HTML was returned instead of JSON. It might help to coax ColdFusion by specifying:
Copy code
cfheader(name="Content-Type", value="application/json")
a
yes that what I've done but I want CF to do that automatically to requests when
returnFormat=json
is specified
b
Hmm, I can feel a CF feature request coming up. 🙂
b
Ahh, you were getting a wddx returnformat which is the default
That wasn't clear from your question
I've found Lucee does a better job of setting the content type based on the return format
a
sorry, what's
wddx
?
b
An xml data transfer format, like json but from the turn of the century
Thats what the <struct> is part of.
a
oh right.
I only get that if I omit
returnFormat=json
and my question is more regarding the response
Content-Type
b
Right, because wddx is the default format
a
which is
html
regardless of what the returnformat is
b
Lucee always sets the matching content type header. I'm actually not sure if Adobe CF ever sets one.
a
for example
returnFormat=json
returns valid json, but with the
text/html
content type. likewise, omitting it, returns presuambly valid wddx but again with `text/html`content tpye
I'd expect one to be
text/json
and I guess the other to be
xml
b
I think the rule if thumb is, if you're not on Lucee, you just need to set your content type because ACF isn't smart enough to do it for you.
a
right
is there a way I can catch whether
returnFormat=json
has been specified and set the content type appropiately?
b
I'm so used to using Lucee I honestly always forget that adobe doesnt "just work".
I don't think so, but maybe if you use an onCFCRequest method
a
interesting
that might warrant some investigation
b
I just implemented this all for BoxLang and I found TONS if differences in the Lucee and ACF implementations
a
I'd like it if we were using Lucee, but we're gonna migrate away from CF altogether I think
b
Adobe will look at the returnformat of the method specified in tbe URL, EVEN IF you call a totally different method in your onCFCRequest
But you can get the metadata of the target method your self
Just know, ACF calls your cfc's pseduocontructor twice when you have an onCFCrequest method which is a bit crap
They create an instance if the CFC to get the method Metadata, even if your oncfcrequest also creates the cfc or calls an entirely different cfc
Its also up to you to verify the method is actually remote in your oncfcrequest. Overall, it wasn't thiught through very well.
a
know how I can check whether the method is 'remote' in
onCFCrequest
?
b
GetMetaData( cfcInstance[ methodName ] )
You can create the target cfc and then inelspect the method before you call it
a
any chance you'd be able to whip up an oncfcrequest function for me ? not having much luck. just want to set the content type to json if it's
remote
&
returnFormat=json
if it's going to take you more than a minute don't worry
b
I'm on my phone. Start with the example in adobe's docs
a
yeah was more the getmetadata
dw
ok got the function metadata working 🙂
👍 1
v close
Copy code
public function onCFCRequest(string cfc, string method, struct args) {
			var component = createObject("component", arguments.cfc);
			var meta = getMetaData(component[method]);
			if (
				meta.keyExists("access")
				&& meta.access == "remote"
				&& URL.keyExists("returnFormat")
				&& URL.returnFormat == "json") {
				cfheader( name="Content-Type", value="text/json" );
			}
			return component[method](args);
		}
think that's it ^ 🙂 seems to work at least
b
Almost there. 🙂 Replace "text/json" with the correct type, which is "application/json". Anyway. I have a question and a remark. (1) Doesn't it make more sense to just plonk the cfheader in any remote function that needs to respond with JSON? (2) I have informed Adobe about what you have reported here. See the bug report: https://tracker.adobe.com/#/view/CF-4223763
a
1. There go knows how many functions our codebase that do this. I don't want to go update every one of them. 2. Nice one
will change to
application/json
well I did have it working. somehow seem to have broken it lol
the arguments don't seem to be getting passed to the method
b
Copy code
@bdw429s: ...you were getting a wddx returnformat which is the default
That was the one. Thanks for the reminder, @bdw429s.
b
Don't you need to use argument collection?
You didn't quite replicate adobes example
You're just passing the arg struct as the first argument.
a
yeah thats it. must've changed that somewhere down the line
ta!
thanks for the assistance @bdw429s @bkbk
👍 1
b
@Alan, I would, in any case, avoid using the word
component
as a variable name.
👍 2
a
🙏
👍 1