Coldfusion: перекрестное решение ACF11/Lucee 4.5 RestInitApplication()

Когда я использую следующий код:

<cftry>
    <cfif CompareNoCase(request.engine,"Railo") EQ 0>
        <cfset RestInitApplication(request.filepath & "\com\api",local.serviceMapping,false,request.webAdminPassword) />
    <cfelse>
        <cfset RestInitApplication(request.filepath & "\com\api",local.serviceMapping) />
    </cfif>
    <cfcatch>
     </cfcatch>
</cftry>

Adobe Coldfusion выдает следующую ошибку компиляции:

Parameter validation error for the RESTINITAPPLICATION function.
The function accepts 1 to 3 parameters. 

Может ли кто-нибудь предложить способ, я могу остановить Coldfusion от выдачи ошибки?

Если я попытаюсь сделать следующее:

<cfif CompareNoCase(request.engine,"Railo") EQ 0>
    <cfset RestInitApplication(dirPath=request.filepath & "\com\api",serviceMapping=local.serviceMapping,password=request.webAdminPassword) />
<cfelse>
    <cfset RestInitApplication( dirPath=request.filepath & "\com\api", serviceMapping=local.serviceMapping) />
</cfif>

ACF выдает другую ошибку компиляции:

Parameter validation error for the RESTINITAPPLICATION function.
A built-in ColdFusion function cannot accept an assignment statement as a parameter, although it can accept expressions. For example, RESTINITAPPLICATION(d=a*b) is not acceptable. 

И если я попытаюсь:

<cfif CompareNoCase(request.engine,"Railo") EQ 0>
  <cfset this.webAdminPassword = request.webAdminPassword />
  <cfset RestInitApplication(request.filepath & "\com\api",local.serviceMapping) />
<cfelse>
  <cfset RestInitApplication(request.filepath & "\com\api",local.serviceMapping) />
</cfif>

Lucee выдает ошибку, говорящую мне, что пароль не определен.

Окружающая среда:

ACF11 в Windows 10

Lucee 4.5 на сервере Windows 2008R2


person Charles Robertson    schedule 08.08.2018    source источник
comment
Любые изменения, если вы укажете имена параметров? т.е. restInitApplication( dirPath=request.filepath & "\com\api"), serviceMapping=local.serviceMapping)   -  person SOS    schedule 08.08.2018
comment
Это хорошая идея, но ACF выдает ошибку компиляции другого рода. Ошибка проверки параметра для функции RESTINITAPPLICATION. Встроенная функция ColdFusion не может принимать оператор присваивания в качестве параметра, хотя и может принимать выражения. Например, RESTINITAPPLICATION(d=a*b) неприемлемо.   -  person Charles Robertson    schedule 08.08.2018
comment
Похоже на то, что упомянуто в этой записи . Функция испорчена, потому что то, что вы пробовали, должно работать, поскольку последние 2 параметра являются необязательными. Во всяком случае, предоставление необязательного третьего параметра (структуры), кажется, заставляет его работать: <cfset restInitApplication( request.filepath & "\com\api", local.serviceMapping, {})>   -  person SOS    schedule 08.08.2018
comment
3 параметра подходят, а 4 нет в ACF. И мне нужно предоставить Люси 4, потому что Пароль, к сожалению, 4-й...   -  person Charles Robertson    schedule 08.08.2018
comment
Тем не менее, я нашел решение, которое было проверено. Это неясно, но я нашел его в документах ACF Rest. Я поставлю его через минуту, но спасибо за вашу помощь. И, да, эта функция глючит, но эта функция, к счастью, не требуется. И это не требует использования CF/Lucee Administrator.   -  person Charles Robertson    schedule 08.08.2018
comment
В приведенном выше примере ACF всего 3 параметра. Вы пробовали? Хотя мне тоже любопытно увидеть ваше решение. (Обновление) Возможно, также потребуется отправить отчет об ошибке.   -  person SOS    schedule 08.08.2018
comment
Да. Я имею в виду, что ACF берет первую часть [Railo/Lucee] условного предложения, которое имеет 4 параметра, и выдает шаткий...   -  person Charles Robertson    schedule 08.08.2018
comment
Я думал, что условное выражение предотвратит отслеживание ACF первой части условного выражения, но поскольку это ошибка времени компиляции, ACF проверяет каждую строку кода...   -  person Charles Robertson    schedule 08.08.2018
comment
Ну, это воняет... но имеет смысл.   -  person SOS    schedule 08.08.2018
comment
Честно говоря, меня больше раздражает Люси за то, что она заставляет нас использовать webAdminPassword. Кажется немного ненужным. В противном случае исходная функция работала бы нормально. Люси виновата в том, что отклонилась от методологии ACF.   -  person Charles Robertson    schedule 08.08.2018
comment
Адам Кэмерон написал об этом и пожаловался на это инженерам Lucee.   -  person Charles Robertson    schedule 08.08.2018
comment
Да, это раздражает... В некоторых случаях я понимаю, почему они хотят отклониться, но не в этом. Хотя Adobe определенно испортила реализацию, просто по-другому :-/   -  person SOS    schedule 08.08.2018
comment
Согласованный. Оба должны поднять свою игру на эту реализацию.   -  person Charles Robertson    schedule 08.08.2018


Ответы (1)


ХОРОШО. Я нашел решение, которое официально поддерживается. Если вы посмотрите официальную документацию Adobe Coldfusion, параграф, озаглавленный «Поддержка приложений REST на уровне сайта», в нижней части страницы:

https://helpx.adobe.com/coldfusion/developing-applications/changes-in-coldfusion/restful-web-services-in-coldfusion.html

В нем говорится, что вы можете использовать:

this.restsettings

Практически для всех:

RestInitApplication()

Параметры.

Я пробовал те, которые он не упоминает, например:

dirPath
password

И это работает.

Итак, вот решение:

<cfif CompareNoCase(request.engine,"Railo") EQ 0>
  <cfset this.restsettings.dirPath = request.filepath & "\com\api" />
  <cfset this.restsettings.serviceMapping = local.serviceMapping />
  <cfset this.restsettings.password = request.webAdminPassword />
<cfelse>
  <cfset this.restsettings.dirPath = request.filepath & "\com\api" />
  <cfset this.restsettings.serviceMapping = local.serviceMapping />
</cfif>

ОБНОВЛЕНИЕ 1

С тех пор я обнаружил, что когда в REST API CFC вносятся изменения, остальное приложение необходимо обновлять.

Это цель:

RestInitApplication()

Итак, я разработал решение для решения этой проблемы, которое на самом деле упрощает рутину. Кажется, единственный параметр, который требуется RestInitApplication(), это:

dirPath

Основываясь на этой новой информации, вот поправка к моему первоначальному ответу:

<cftry>
  <cfif CompareNoCase(request.engine,"Railo") EQ 0>
    <cfset this.restsettings.password = request.webAdminPassword />
  </cfif>
  <cfset restInitApplication(local.dirPath,local.serviceMapping)>
  <cfcatch>
  </cfcatch>
</cftry>

Фактически вы можете удалить второй параметр и заменить его на:

<cfset this.restsettings.serviceMapping = local.serviceMapping />

Но я оставлю это решение на ваше усмотрение!

ОБНОВЛЕНИЕ 2:

Поговорив с Шоном Корфилдом, он также предложил другой подход, действительно умный.

С использованием:

<cfinclude>

В качестве контейнера для каждой версии restInitApplication()

Код не выдаст ошибку во время компиляции, даже если нарушение количества параметров все еще существует. cfinclude действует как буфер, когда помещается внутрь условного предложения.

Итак, вот второе решение, и, на мой взгляд, самое чистое, потому что оно инициализирует REST API так, как это должно быть сделано:

<cfif CompareNoCase(request.engine,"Railo") EQ 0>
  <cfset restinitdirpath = local.dirPath>
  <cfset restinitservicemapping = local.serviceMapping>
  <cfset restinitdefault = false>
  <cfset restinitpassword = request.webAdminPassword>
  <cfinclude template="includes/structures/rest/railo-rest-init-structure.cfm">
<cfelse>
  <cfset restinitdirpath = local.dirPath>
  <cfset restinitservicemapping = local.serviceMapping>
  <cfinclude template="includes/structures/rest/coldfusion-rest-init-structure.cfm">
</cfif>

railo-rest-init-structure.cfm

<cfoutput>

  <cfparam name="restinitdirpath" default="">
  <cfparam name="restinitservicemapping" default="">
  <cfparam name="restinitdefault" default="false">
  <cfparam name="restinitpassword" default="">

  <cfset restInitApplication(restinitdirpath,restinitservicemapping,restinitdefault,restinitpassword)>

</cfoutput>

coldfusion-rest-init-structure.cfm

<cfoutput>

  <cfparam name="restinitdirpath" default="">
  <cfparam name="restinitservicemapping" default="">

  <cfset restInitApplication(restinitdirpath,restinitservicemapping)>

</cfoutput>

Теперь я протестировал это, и оно работает, и любые изменения, внесенные в ваши REST API CFC, впоследствии будут обнаруживаться каждый раз при нажатии restInitApplication().

person Charles Robertson    schedule 08.08.2018
comment
Хорошая находка. Спасибо, что написали :) - person SOS; 08.08.2018
comment
Упс. Я лучше возьму свой пароль открытым текстом. Дох! - person Charles Robertson; 08.08.2018
comment
.. и для безопасности тоже поменяйте ;-) - person SOS; 08.08.2018
comment
Да. Пароль хранится в БД в зашифрованном виде, а соль — в отдельной защищенной БД. - person Charles Robertson; 08.08.2018
comment
Можете ли вы просто использовать this.restsettings..., чтобы установить все 3 для всех сред и просто проверить наличие request.webAdminPassword? Вам, вероятно, не нужно дублировать код (dirpath и serviceMapping`). - person Shawn; 08.08.2018
comment
Хорошая идея @Shawn Я действительно решил вообще отказаться от использования REST API, потому что использование кросс-совместимого решения полно проблем. Например, поскольку я больше не использую RestInitApplication, система больше не может обновляться при внесении изменений в REST CFC. На самом деле, когда я пытался решить эту проблему, это повредило весь сервер приложений. Пришлось переустанавливать, ACF. Я использую его только для выдачи токенов обновления, поэтому вместо этого я буду использовать простой компонентный метод CFC. Может все эти проблемы были решены в ACF2016+ и Lucee 5+? - person Charles Robertson; 08.08.2018
comment
@Shawn Тем не менее, я думаю, что нашел решение проблемы с обновлением REST API, что очень важно. Завтра я дополню свой ответ последней частью головоломки l. Я настроен победить эту проблему... - person Charles Robertson; 08.08.2018
comment
Аккуратный! Я предпочитаю обновление №1, потому что логика находится в одном месте, но полезно знать о cfinclude. Не знал, что это может обойти проверку времени компиляции! - person SOS; 09.08.2018
comment
@Ageax Да. Шон, действительно удивил меня этой жемчужиной! Хм. Возможно, вы правы в том, что обновление №1 лучше. Конечно короче! Вы также можете использовать this.webAdminPassword = '123456' вместо this.restsettings.password = '123456'. Итак, существует довольно много различных подходов, доступных... - person Charles Robertson; 09.08.2018
comment
Это потому что он волшебник ;-) - person SOS; 09.08.2018