001package ca.uhn.fhir.rest.server.method; 002 003/*- 004 * #%L 005 * HAPI FHIR - Server Framework 006 * %% 007 * Copyright (C) 2014 - 2019 University Health Network 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import ca.uhn.fhir.context.FhirContext; 024import ca.uhn.fhir.interceptor.api.HookParams; 025import ca.uhn.fhir.interceptor.api.Pointcut; 026import ca.uhn.fhir.rest.api.Constants; 027import ca.uhn.fhir.rest.api.RestOperationTypeEnum; 028import ca.uhn.fhir.rest.api.server.IRestfulServer; 029import ca.uhn.fhir.rest.api.server.RequestDetails; 030import ca.uhn.fhir.rest.api.server.ResponseDetails; 031import ca.uhn.fhir.rest.param.ParameterUtil; 032import ca.uhn.fhir.rest.param.TokenParam; 033import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; 034import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; 035import org.hl7.fhir.instance.model.api.IBaseCoding; 036import org.hl7.fhir.instance.model.api.IBaseResource; 037 038import javax.annotation.Nonnull; 039import javax.servlet.http.HttpServletRequest; 040import javax.servlet.http.HttpServletResponse; 041import java.io.IOException; 042import java.io.Writer; 043import java.lang.reflect.Method; 044 045public class GraphQLMethodBinding extends BaseMethodBinding<String> { 046 047 private final Integer myIdParamIndex; 048 049 public GraphQLMethodBinding(Method theMethod, FhirContext theContext, Object theProvider) { 050 super(theMethod, theContext, theProvider); 051 052 myIdParamIndex = ParameterUtil.findIdParameterIndex(theMethod, theContext); 053 } 054 055 @Override 056 public String getResourceName() { 057 return null; 058 } 059 060 @Nonnull 061 @Override 062 public RestOperationTypeEnum getRestOperationType() { 063 return RestOperationTypeEnum.GRAPHQL_REQUEST; 064 } 065 066 @Override 067 public boolean isGlobalMethod() { 068 return true; 069 } 070 071 @Override 072 public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) { 073 if (Constants.OPERATION_NAME_GRAPHQL.equals(theRequest.getOperation())) { 074 return true; 075 } 076 077 return false; 078 } 079 080 @Override 081 public Object invokeServer(IRestfulServer<?> theServer, RequestDetails theRequest) throws BaseServerResponseException, IOException { 082 Object[] methodParams = createMethodParams(theRequest); 083 if (myIdParamIndex != null) { 084 methodParams[myIdParamIndex] = theRequest.getId(); 085 } 086 087 Object response = invokeServerMethod(theServer, theRequest, methodParams); 088 089 int statusCode = Constants.STATUS_HTTP_200_OK; 090 String statusMessage = Constants.HTTP_STATUS_NAMES.get(statusCode); 091 String contentType = Constants.CT_JSON; 092 String charset = Constants.CHARSET_NAME_UTF8; 093 boolean respondGzip = theRequest.isRespondGzip(); 094 095 String responseString = (String) response; 096 097 HttpServletRequest servletRequest=null; 098 HttpServletResponse servletResponse=null; 099 if (theRequest instanceof ServletRequestDetails) { 100 servletRequest = ((ServletRequestDetails) theRequest).getServletRequest(); 101 servletResponse = ((ServletRequestDetails) theRequest).getServletResponse(); 102 } 103 104 // Interceptor call: SERVER_OUTGOING_GRAPHQL_RESPONSE 105 HookParams params = new HookParams() 106 .add(RequestDetails.class, theRequest) 107 .addIfMatchesType(ServletRequestDetails.class, theRequest) 108 .add(String.class, theRequest.getParameters().get(Constants.PARAM_GRAPHQL_QUERY)[0]) 109 .add(String.class, responseString) 110 .add(HttpServletRequest.class, servletRequest) 111 .add(HttpServletResponse.class, servletResponse); 112 if (!theRequest.getInterceptorBroadcaster().callHooks(Pointcut.SERVER_OUTGOING_GRAPHQL_RESPONSE, params)) { 113 return null; 114 } 115 116 // Interceptor call: SERVER_OUTGOING_RESPONSE 117 params = new HookParams() 118 .add(RequestDetails.class, theRequest) 119 .addIfMatchesType(ServletRequestDetails.class, theRequest) 120 .add(IBaseResource.class, null) 121 .add(ResponseDetails.class, new ResponseDetails()) 122 .add(HttpServletRequest.class, servletRequest) 123 .add(HttpServletResponse.class, servletResponse); 124 if (!theRequest.getInterceptorBroadcaster().callHooks(Pointcut.SERVER_OUTGOING_RESPONSE, params)) { 125 return null; 126 } 127 128 // Write the response 129 Writer writer = theRequest.getResponse().getResponseWriter(statusCode, statusMessage, contentType, charset, respondGzip); 130 writer.write(responseString); 131 writer.close(); 132 133 134 return null; 135 } 136}