Search code examples
azureazureservicebus

How to get notification from azure service bus topic from frontend?


we are using azure-service-bus for notification services. in azure portal., service bus topic has been created and message is available in topic. Iam trying to use REST API services to get the topic data.

This is the code I have currently.

import axios from 'axios';

const namespace = 'my-namespace';
const topicName = 'my-topic-name';
const subscriptionId = 'my-subscription-id';
const accesskey = 'my-access-key';

const baseurl = `https://${namespace}.servicebus.windoes.net`;
const url = `${baseurl}/${topicName}/subscriptions/${subscriptionId}`;
const headers = {
  Authorization: `SharedAccessSignature ${accesskey}`,
  'content-type': 'application/json',
}

const getDetails = async () => {
  try {
    const response = await axios.get(url, { headers });
    console.log('response', response.data);
  } catch (error) {
    console.error('error', error);
  }
}

export default getDetails;

I currently have very limited understanding on what is required in frontend. I was trying to use @azure/service-bus., but it is giving error cant resolve 'os' in rhea., webpack < 5 used error.

Hence I tried to eliminate the dependency and used https services.

iam currentlu getting 401 unauthorized error.

can you guide me where iam doing wrong?

updated code as per suggestions:

import axios from 'axios';
import { SHA256 } from 'crypto-js';
   
const sbName = 'my-sb-name';
const topicName = 'my-topic-name';
const sharedAccessKey = 'my-shared-access-key';
const sharedAccessName = 'RootManagerSharedAccessKey';
const expiry = Math.floor(Date.now() / 1000) + 10000;
const baseUrl = `https://${sbName}.servicebus.windows.net`;
const url = `${baseUrl}/${topicName}`;
const toSign = `${url}\n${expiry.toString()}`;
const signature = SHA256(toSign).toString();
const encodedSignature = encodeURIComponent(signature);
const authFormat = `SharedAccessSignature sig={0}&se={1}&skn={2}$sr={3}`;
const auth = authFormat
  .replace('{0}', encodedSignature)
  .replace('{1}', expiry.toString())
  .replace('{2}', sharedAccessName)
  .replace('{3}', url);

console.log(auth);

const headers = {
  Authorization: auth,
  'Content-Type': 'application/json',
};

const getDetails = async () => {
  try {
    const response = await axios.get(url, { headers });
    console.log('Queue Details:', response.data);
    // Process the response or update your UI with the retrieved queue details
  } catch (error) {
    console.error('Error retrieving queue details:', error);
  }
};
// Call the function to get queue details
export default getDetails;

which gives error: 401 unauthorized


Solution

  • I used @azure/service-bus and configured the dependencies as suggested in their official documentaion and it worked.

    Iam using react-scripts for my react 18 app. So., inorder to merge the recommended config with react-scripts., I installed @craco/craco as dev dependency.

    in my craco.config.js added following configuration:

    const webpack = require('webpack');
    
    module.exports = {
      webpack: {
        configure: (webpackConfig) => {
          webpackConfig.resolve.fallback = {
            ...webpackConfig.resolve.fallback,
            os: require.resolve('os-browserify/browser'),
            path: require.resolve('path-browserify'),
            buffer: require.resolve('buffer/'),
            process: require.resolve('process/browser'),
          }
          webpackConfig.plugins.push(
            new webpack.ProvidePlugin({
              Buffer: ['buffer', 'Buffer'],
              process: 'process/browser'
            })
          );
          return webpackConfig;
        }
      }
    }

    and in my "scripts" in package.json., replaced react-scripts start to craco start as below:

    "start": "craco start",
    "build": "craco build",

    in my getServiceTopicMessage.js

    import { ServiceBusClient } from '@azure/service-bus';
    
    async function getServiceBusTopicMessage() {
      const connectionString = 'your connection string';
      const topicName = 'your topic name';
      const subscriptionName = 'your subscription name';
      
      const serviceBusClient = new ServiceBusClient(connectionString);
      const receiver = serviceBusClient.createReceiver(topicName, subscriptionName);
      
      try {
        console.log('waiting for messages...');
        while(true) {
          const messages = await receiver.receiveMessages(1, {maxWaitTimeInMs: 5000});
        if(messages.length > 0) {
          console.log(messages[0].body);
          await receiver.completeMessage(messages[0]);
        }
      }
      } catch (error) {
        console.error(error);
      } finally {
        await receiver.close();
        await serviceBusClient.close();
      }
    }
    export default getServiceBusTopicMessage;

    and just import the function in your required page and call. it works